[
  {
    "path": "README.md",
    "content": "WebGL Deferred Irradiance Volumes\n=================================\n\nAn implementation of global illumination using deferred application of irradiance probes.\n\nDocumentation\n-------------\n\nBlog entry outlining the basic principle: http://codeflow.org/entries/2012/aug/25/webgl-deferred-irradiance-volumes/\n\nDemo\n----\n\nLive Demo at: http://codeflow.org/webgl/deferred-irradiance-volumes/www/\n\nLicense\n-------\n\nCopyright (c) 2012, Florian Boesch <pyalot@gmail.com> http://codeflow.org/\n\nWebGL Deferred Irradiance Volumes is licensed under any of the following licenses at your choosing:\n\n * MIT: see mit-license\n * GPL: see gplv*-license\n * BSD: see bsd-license\n"
  },
  {
    "path": "build",
    "content": "#!/usr/bin/env python\n\n'''\nCopy this into your bin directory for convenient building\n'''\n\nimport os, subprocess\n\nhere = os.getcwd()\nfolders = here.split('/')\n\nwhile folders:\n    path = '/'.join(folders)\n    scriptpath = os.path.join(path, 'build.sh')\n    if os.path.exists(scriptpath):\n        os.chdir(path)\n        subprocess.call(['bash', 'build.sh'])\n        break\n    folders.pop()\n"
  },
  {
    "path": "build.sh",
    "content": "./compile\n./pack\n"
  },
  {
    "path": "compile",
    "content": "#!/usr/bin/env python\n\nimport os, sys, stat, subprocess\nfrom datetime import datetime\n\nhere = os.path.dirname(os.path.abspath(__file__))\n\nmessage_count = 0\ndef message(text):\n    global message_count\n    now = datetime.now().strftime('%H:%M:%S')\n    print '[%04i %s] %s' % (message_count, now, text)\n    message_count+=1\n\ndef error(text):\n    sys.stdout.write('\\x1b[31m%s\\x1b[39m' % text)\n    sys.stdout.flush()\n\ndef coffee_compile(path, bare):\n    message('compiling: %s' % path)\n    if bare:\n        command = ['coffee', '--compile', '--bare', path]\n    else:\n        command = ['coffee', '--compile', path]\n\n    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)\n    out, err = process.communicate()\n    if process.returncode:\n        error(err)\n\ndef get_mtime(name):\n    return os.stat(name)[stat.ST_MTIME]\n\ndef listfiles(folder, *exts):\n    for path, dirs, names in os.walk(os.path.join(here, folder)):\n        for name in names:\n            ext = os.path.splitext(name)[-1].lstrip('.')\n            if ext in exts:\n                yield path, name, os.path.join(path, name)\n\ndef check_files(folder, bare):\n    for path, name, loc in listfiles(folder, 'coffee'):\n        js_path = os.path.join(path, os.path.splitext(name)[0] + '.js')\n        coffee_mtime = get_mtime(loc)\n        if os.path.exists(js_path):\n            js_mtime = get_mtime(js_path)\n            if coffee_mtime > js_mtime:\n                coffee_compile(loc, bare=bare)\n        else:\n            coffee_compile(loc, bare=bare)\n\nif __name__ == '__main__':\n    check_files('src', bare=True)\n    check_files('lib', bare=True)\n    check_files('extra', bare=False)\n"
  },
  {
    "path": "extra/Stats.js",
    "content": "/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar Stats = function () {\n\n\tvar startTime = Date.now(), prevTime = startTime;\n\tvar ms = 0, msMin = 1000, msMax = 0;\n\tvar fps = 0, fpsMin = 1000, fpsMax = 0;\n\tvar frames = 0, mode = 0;\t\n\n\tvar container = document.createElement( 'div' );\n\tcontainer.id = 'stats';\n\tcontainer.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false );\n\tcontainer.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';\n\n\tvar fpsDiv = document.createElement( 'div' );\n\tfpsDiv.id = 'fps';\n\tfpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';\n\tcontainer.appendChild( fpsDiv );\n\n\tvar fpsText = document.createElement( 'div' );\n\tfpsText.id = 'fpsText';\n\tfpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n\tfpsText.innerHTML = 'FPS';\n\tfpsDiv.appendChild( fpsText );\n\n\tvar fpsGraph = document.createElement( 'div' );\n\tfpsGraph.id = 'fpsGraph';\n\tfpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';\n\tfpsDiv.appendChild( fpsGraph );\n\n\twhile ( fpsGraph.children.length < 74 ) {\n\n\t\tvar bar = document.createElement( 'span' );\n\t\tbar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';\n\t\tfpsGraph.appendChild( bar );\n\n\t}\n\n\tvar msDiv = document.createElement( 'div' );\n\tmsDiv.id = 'ms';\n\tmsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';\n\tcontainer.appendChild( msDiv );\n\n\tvar msText = document.createElement( 'div' );\n\tmsText.id = 'msText';\n\tmsText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n\tmsText.innerHTML = 'MS';\n\tmsDiv.appendChild( msText );\n\n\tvar msGraph = document.createElement( 'div' );\n\tmsGraph.id = 'msGraph';\n\tmsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';\n\tmsDiv.appendChild( msGraph );\n\n\twhile ( msGraph.children.length < 74 ) {\n\n\t\tvar bar = document.createElement( 'span' );\n\t\tbar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';\n\t\tmsGraph.appendChild( bar );\n\n\t}\n\n\tvar setMode = function ( value ) {\n\n\t\tmode = value;\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase 0:\n\t\t\t\tfpsDiv.style.display = 'block';\n\t\t\t\tmsDiv.style.display = 'none';\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfpsDiv.style.display = 'none';\n\t\t\t\tmsDiv.style.display = 'block';\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\tvar updateGraph = function ( dom, value ) {\n\n\t\tvar child = dom.appendChild( dom.firstChild );\n\t\tchild.style.height = value + 'px';\n\n\t}\n\n\treturn {\n\n\t\tdomElement: container,\n\n\t\tsetMode: setMode,\n\n\t\tbegin: function () {\n\n\t\t\tstartTime = Date.now();\n\n\t\t},\n\n\t\tend: function () {\n\n\t\t\tvar time = Date.now();\n\n\t\t\tms = time - startTime;\n\t\t\tmsMin = Math.min( msMin, ms );\n\t\t\tmsMax = Math.max( msMax, ms );\n\n\t\t\tmsText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';\n\t\t\tupdateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) );\n\n\t\t\tframes ++;\n\n\t\t\tif ( time > prevTime + 1000 ) {\n\n\t\t\t\tfps = Math.round( ( frames * 1000 ) / ( time - prevTime ) );\n\t\t\t\tfpsMin = Math.min( fpsMin, fps );\n\t\t\t\tfpsMax = Math.max( fpsMax, fps );\n\n\t\t\t\tfpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';\n\t\t\t\tupdateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) );\n\n\t\t\t\tprevTime = time;\n\t\t\t\tframes = 0;\n\n\t\t\t}\n\n\t\t\treturn time;\n\n\t\t},\n\n\t\tupdate: function () {\n\n\t\t\tstartTime = this.end();\n\t\t\t\n\t\t}\n\n\t}\n\t\n};\n"
  },
  {
    "path": "extra/jquery.js",
    "content": "/*! jQuery v1.7.2 jquery.com | jquery.org/license */\n(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f(\"<\"+a+\">\").appendTo(b),e=d.css(\"display\");d.remove();if(e===\"none\"||e===\"\"){ck||(ck=c.createElement(\"iframe\"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?\"<!doctype html>\":\"\")+\"<html><body>\"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,\"display\"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h==\"string\"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k===\"*\")k=l;else if(l!==\"*\"&&l!==k){m=l+\" \"+k,n=e[m]||e[\"* \"+k];if(!n){p=b;for(o in e){j=o.split(\" \");if(j[0]===l||j[0]===\"*\"){p=e[j[1]+\" \"+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error(\"No conversion from \"+m.replace(\" \",\" to \")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]===\"*\")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader(\"content-type\"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+\" \"+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+\"[\"+(typeof e==\"object\"?b:\"\")+\"]\",e,c,d)});else if(!c&&f.type(b)===\"object\")for(var e in b)b_(a+\"[\"+e+\"]\",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l==\"string\"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g[\"*\"]&&(l=bZ(a,c,d,e,\"*\",g));return l}function bY(a){return function(b,c){typeof b!=\"string\"&&(c=b,b=\"*\");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\\+/.test(h),j&&(h=h.substr(1)||\"*\"),i=a[h]=a[h]||[],i[j?\"unshift\":\"push\"](c)}}}function bB(a,b,c){var d=b===\"width\"?a.offsetWidth:a.offsetHeight,e=b===\"width\"?1:0,g=4;if(d>0){if(c!==\"border\")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,\"padding\"+bx[e]))||0),c===\"margin\"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,\"border\"+bx[e]+\"Width\"))||0;return d+\"px\"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,\"padding\"+bx[e]))||0,c!==\"padding\"&&(d+=parseFloat(f.css(a,\"border\"+bx[e]+\"Width\"))||0),c===\"margin\"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+\"px\"}function bo(a){var b=c.createElement(\"div\");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||\"\").toLowerCase();b===\"input\"?bm(a):b!==\"script\"&&typeof a.getElementsByTagName!=\"undefined\"&&f.grep(a.getElementsByTagName(\"input\"),bm)}function bm(a){if(a.type===\"checkbox\"||a.type===\"radio\")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!=\"undefined\"?a.getElementsByTagName(\"*\"):typeof a.querySelectorAll!=\"undefined\"?a.querySelectorAll(\"*\"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c===\"object\"?b.outerHTML=a.outerHTML:c!==\"input\"||a.type!==\"checkbox\"&&a.type!==\"radio\"?c===\"option\"?b.selected=a.defaultSelected:c===\"input\"||c===\"textarea\"?b.defaultValue=a.defaultValue:c===\"script\"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute(\"_submit_attached\"),b.removeAttribute(\"_change_attached\"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,\"table\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function U(a){var b=V.split(\"|\"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b==\"string\"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+\"defer\",e=b+\"queue\",g=b+\"mark\",h=f._data(a,d);h&&(c===\"queue\"||!f._data(a,e))&&(c===\"mark\"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b===\"data\"&&f.isEmptyObject(a[b]))continue;if(b!==\"toJSON\")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e=\"data-\"+c.replace(k,\"-$1\").toLowerCase();d=a.getAttribute(e);if(typeof d==\"string\"){try{d=d===\"true\"?!0:d===\"false\"?!1:d===\"null\"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll(\"left\")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,j=/\\S/,k=/^\\s+/,l=/\\s+$/,m=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,n=/^[\\],:{}\\s]*$/,o=/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,q=/(?:^|:|,)(?:\\s*\\[)+/g,r=/(webkit)[ \\/]([\\w.]+)/,s=/(opera)(?:.*version)?[ \\/]([\\w.]+)/,t=/(msie) ([\\w.]+)/,u=/(mozilla)(?:.*? rv:([\\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+\"\").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a===\"body\"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a==\"string\"){a.charAt(0)!==\"<\"||a.charAt(a.length-1)!==\">\"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:\"\",jquery:\"1.7.2\",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b===\"find\"?d.selector=this.selector+(this.selector?\" \":\"\")+c:b&&(d.selector=this.selector+\".\"+b+\"(\"+c+\")\");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),\"slice\",F.call(arguments).join(\",\"))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==\"boolean\"&&(l=i,i=arguments[1]||{},j=2),typeof i!=\"object\"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger(\"ready\").off(\"ready\")}},bindReady:function(){if(!A){A=e.Callbacks(\"once memory\");if(c.readyState===\"complete\")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener(\"DOMContentLoaded\",B,!1),a.addEventListener(\"load\",e.ready,!1);else if(c.attachEvent){c.attachEvent(\"onreadystatechange\",B),a.attachEvent(\"onload\",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)===\"function\"},isArray:Array.isArray||function(a){return e.type(a)===\"array\"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||\"object\"},isPlainObject:function(a){if(!a||e.type(a)!==\"object\"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,\"constructor\")&&!D.call(a.constructor.prototype,\"isPrototypeOf\"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!=\"string\"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,\"@\").replace(p,\"]\").replace(q,\"\")))return(new Function(\"return \"+b))();e.error(\"Invalid JSON: \"+b)},parseXML:function(c){if(typeof c!=\"string\"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,\"text/xml\")):(d=new ActiveXObject(\"Microsoft.XMLDOM\"),d.async=\"false\",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName(\"parsererror\").length)&&e.error(\"Invalid XML: \"+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,\"ms-\").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?\"\":G.call(a)}:function(a){return a==null?\"\":(a+\"\").replace(k,\"\").replace(l,\"\")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d===\"string\"||d===\"function\"||d===\"regexp\"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length==\"number\")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j==\"number\"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c==\"string\"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d==\"object\"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf(\"compatible\")<0&&u.exec(a)||[];return{browser:b[1]||\"\",version:b[2]||\"0\"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"),function(a,b){I[\"[object \"+b+\"]\"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(\" \")&&(k=/^[\\s\\xA0]+/,l=/[\\s\\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener(\"DOMContentLoaded\",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState===\"complete\"&&(c.detachEvent(\"onreadystatechange\",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h===\"array\"?n(g):h===\"function\"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks(\"once memory\"),c=f.Callbacks(\"once memory\"),d=f.Callbacks(\"memory\"),e=\"pending\",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,\"resolve\"],fail:[b,\"reject\"],progress:[c,\"notify\"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+\"With\"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+\"With\"]=g[j].fireWith;i.done(function(){e=\"resolved\"},c.disable,d.lock).fail(function(){e=\"rejected\"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement(\"div\"),q=c.documentElement;p.setAttribute(\"className\",\"t\"),p.innerHTML=\"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\",d=p.getElementsByTagName(\"*\"),e=p.getElementsByTagName(\"a\")[0];if(!d||!d.length||!e)return{};g=c.createElement(\"select\"),h=g.appendChild(c.createElement(\"option\")),i=p.getElementsByTagName(\"input\")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName(\"tbody\").length,htmlSerialize:!!p.getElementsByTagName(\"link\").length,style:/top/.test(e.getAttribute(\"style\")),hrefNormalized:e.getAttribute(\"href\")===\"/a\",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value===\"on\",optSelected:h.selected,getSetAttribute:p.className!==\"t\",enctype:!!c.createElement(\"form\").enctype,html5Clone:c.createElement(\"nav\").cloneNode(!0).outerHTML!==\"<:nav></:nav>\",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode===\"CSS1Compat\",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent(\"onclick\",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent(\"onclick\")),i=c.createElement(\"input\"),i.value=\"t\",i.setAttribute(\"type\",\"radio\"),b.radioValue=i.value===\"t\",i.setAttribute(\"checked\",\"checked\"),i.setAttribute(\"name\",\"t\"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m=\"on\"+n,o=m in p,o||(p.setAttribute(m,\"return;\"),o=typeof p[m]==\"function\"),b[n+\"Bubbles\"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName(\"body\")[0];!u||(m=1,t=\"padding:0;margin:0;border:\",r=\"position:absolute;top:0;left:0;width:1px;height:1px;\",s=t+\"0;visibility:hidden;\",n=\"style='\"+r+t+\"5px solid #000;\",q=\"<div \"+n+\"display:block;'><div style='\"+t+\"0;display:block;overflow:hidden;'></div></div>\"+\"<table \"+n+\"' cellpadding='0' cellspacing='0'>\"+\"<tr><td></td></tr></table>\",d=c.createElement(\"div\"),d.style.cssText=s+\"width:0;height:0;position:static;top:0;margin-top:\"+m+\"px\",u.insertBefore(d,u.firstChild),p=c.createElement(\"div\"),d.appendChild(p),p.innerHTML=\"<table><tr><td style='\"+t+\"0;display:none'></td><td>t</td></tr></table>\",k=p.getElementsByTagName(\"td\"),o=k[0].offsetHeight===0,k[0].style.display=\"\",k[1].style.display=\"none\",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML=\"\",l=c.createElement(\"div\"),l.style.width=\"0\",l.style.marginRight=\"0\",p.style.width=\"2px\",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!=\"undefined\"&&(p.innerHTML=\"\",p.style.width=p.style.padding=\"1px\",p.style.border=0,p.style.overflow=\"hidden\",p.style.display=\"inline\",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display=\"block\",p.style.overflow=\"visible\",p.innerHTML=\"<div style='width:5px;'></div>\",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position=\"fixed\",g.style.top=\"20px\",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top=\"\",e.style.overflow=\"hidden\",e.style.position=\"relative\",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop=\"1%\",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!==\"1%\"),typeof d.style.zoom!=\"undefined\"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\\{.*\\}|\\[.*\\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:\"jQuery\"+(f.fn.jquery+Math.random()).replace(/\\D/g,\"\"),noData:{embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c==\"string\",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c===\"events\";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c==\"object\"||typeof c==\"function\")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(\" \")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute(\"classid\")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,\"parsedAttrs\")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf(\"data-\")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,\"parsedAttrs\",!0)}}return m}if(typeof a==\"object\")return this.each(function(){f.data(this,a)});d=a.split(\".\",2),d[1]=d[1]?\".\"+d[1]:\"\",e=d[1]+\"!\";return f.access(this,function(c){if(c===b){m=this.triggerHandler(\"getData\"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler(\"setData\"+e,d),f.data(this,a,c),b.triggerHandler(\"changeData\"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||\"fx\")+\"mark\",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||\"fx\";var d=c+\"mark\",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,\"mark\"))}},queue:function(a,b,c){var d;if(a){b=(b||\"fx\")+\"queue\",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||\"fx\";var c=f.queue(a,b),d=c.shift(),e={};d===\"inprogress\"&&(d=c.shift()),d&&(b===\"fx\"&&c.unshift(\"inprogress\"),f._data(a,b+\".run\",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+\"queue \"+b+\".run\",!0),n(a,b,\"queue\"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!=\"string\"&&(c=a,a=\"fx\",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a===\"fx\"&&b[0]!==\"inprogress\"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||\"fx\";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!=\"string\"&&(c=a,a=b),a=a||\"fx\";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+\"defer\",j=a+\"queue\",k=a+\"mark\",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks(\"once memory\"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\\n\\t\\r]/g,p=/\\s+/,q=/\\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=\" \"+e.className+\" \";for(h=0,i=b.length;h<i;h++)~g.indexOf(\" \"+b[h]+\" \")||(g+=b[h]+\" \");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"||a===b){c=(a||\"\").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(\" \"+g.className+\" \").replace(o,\" \");for(i=0,j=c.length;i<j;i++)h=h.replace(\" \"+c[i]+\" \",\" \");g.className=f.trim(h)}else g.className=\"\"}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b==\"boolean\";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c===\"string\"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?\"addClass\":\"removeClass\"](e)}else if(c===\"undefined\"||c===\"boolean\")this.className&&f._data(this,\"__className__\",this.className),this.className=this.className||a===!1?\"\":f._data(this,\"__className__\")||\"\"})},hasClass:function(a){var b=\" \"+a+\" \",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(\" \"+this[c].className+\" \").replace(o,\" \").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h=\"\":typeof h==\"number\"?h+=\"\":f.isArray(h)&&(h=f.map(h,function(a){return a==null?\"\":a+\"\"})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!(\"set\"in c)||c.set(this,h,\"value\")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&\"get\"in c&&(d=c.get(g,\"value\"))!==b)return d;d=g.value;return typeof d==\"string\"?d.replace(q,\"\"):d==null?\"\":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type===\"select-one\";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute(\"disabled\")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,\"optgroup\"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find(\"option\").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute==\"undefined\")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&\"set\"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,\"\"+d);return d}if(h&&\"get\"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,\"\"),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error(\"type property can't be changed\");else if(!f.support.radioValue&&b===\"radio\"&&f.nodeName(a,\"input\")){var c=a.value;a.setAttribute(\"type\",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,\"button\"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,\"button\"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&\"set\"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&\"get\"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode(\"tabindex\");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!=\"boolean\"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!==\"\":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+\"\"}},f.attrHooks.tabindex.set=w.set,f.each([\"width\",\"height\"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===\"\"){a.setAttribute(b,\"auto\");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===\"\"&&(b=\"false\"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each([\"href\",\"src\",\"width\",\"height\"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=\"\"+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype=\"encoding\"),f.support.checkOn||f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]={get:function(a){return a.getAttribute(\"value\")===null?\"on\":a.value}}}),f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\\.]*)?(?:\\.(.+))?$/,B=/(?:^|\\s)hover(\\.\\S+)?\\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,G=function(\na){var b=F.exec(a);b&&(b[1]=(b[1]||\"\").toLowerCase(),b[3]=b[3]&&new RegExp(\"(?:^|\\\\s)\"+b[3]+\"(?:\\\\s|$)\"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c[\"class\"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,\"mouseenter$1 mouseleave$1\")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!=\"undefined\"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(\" \");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||\"\").split(\".\").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(\".\")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent(\"on\"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||\"\")).split(\" \");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp(\"(^|\\\\.)\"+l.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d===\"**\"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,[\"events\",\"handle\"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf(\"!\")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(\".\")>=0&&(i=h.split(\".\"),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c==\"object\"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join(\".\"),c.namespace_re=c.namespace?new RegExp(\"(^|\\\\.)\"+i.join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\"):null,o=h.indexOf(\":\")<0?\"on\"+h:\"\";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,\"events\")||{})[c.type]&&f._data(m,\"handle\"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!==\"click\"||!f.nodeName(e,\"a\"))&&f.acceptData(e)&&o&&e[h]&&(h!==\"focus\"&&h!==\"blur\"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,\"events\")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!==\"click\")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:\"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:\"focusin\"},blur:{delegateType:\"focusout\"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent(\"on\"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,\"form\"))return!1;f.event.add(this,\"click._submit keypress._submit\",function(a){var c=a.target,d=f.nodeName(c,\"input\")||f.nodeName(c,\"button\")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,\"submit._submit\",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate(\"submit\",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,\"form\"))return!1;f.event.remove(this,\"._submit\")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type===\"checkbox\"||this.type===\"radio\")f.event.add(this,\"propertychange._change\",function(a){a.originalEvent.propertyName===\"checked\"&&(this._just_changed=!0)}),f.event.add(this,\"click._change\",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate(\"change\",this,a,!0))});return!1}f.event.add(this,\"beforeactivate._change\",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,\"change._change\",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate(\"change\",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!==\"radio\"&&b.type!==\"checkbox\")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,\"._change\");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a==\"object\"){typeof c!=\"string\"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c==\"string\"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+\".\"+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a==\"object\"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c==\"function\")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||\"**\",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,\"**\"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,\"lastToggle\"+a.guid)||0)%d;f._data(this,\"lastToggle\"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!=\"string\"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,d=\"sizcache\"+(Math.random()+\"\").replace(\".\",\"\"),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\\\/g,k=/\\r\\n/g,l=/\\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=\"string\")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(\"\"),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]===\"~\"||w[0]===\"+\")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q=\"\",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)===\"[object Array]\")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!==\"\\\\\"){g[1]=(g[1]||\"\").replace(j,\"\"),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],\"\");break}}}}d||(d=typeof b.getElementsByTagName!=\"undefined\"?b.getElementsByTagName(\"*\"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)===\"\\\\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],\"\");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e=\"\";if(d){if(d===1||d===9||d===11){if(typeof a.textContent==\"string\")return a.textContent;if(typeof a.innerText==\"string\")return a.innerText.replace(k,\"\");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:[\"ID\",\"NAME\",\"TAG\"],match:{ID:/#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,CLASS:/\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,NAME:/\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,ATTR:/\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,TAG:/^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,PSEUDO:/:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/},leftMatch:{},attrMap:{\"class\":\"className\",\"for\":\"htmlFor\"},attrHandle:{href:function(a){return a.getAttribute(\"href\")},type:function(a){return a.getAttribute(\"type\")}},relative:{\"+\":function(a,b){var c=typeof b==\"string\",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},\">\":function(a,b){var c,d=typeof b==\"string\",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},\"\":function(a,b,c){var d,f=e++,g=x;typeof b==\"string\"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g(\"parentNode\",b,f,a,d,c)},\"~\":function(a,b,c){var d,f=e++,g=x;typeof b==\"string\"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g(\"previousSibling\",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=\"undefined\"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!=\"undefined\"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute(\"name\")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=\"undefined\")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=\" \"+a[1].replace(j,\"\")+\" \";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(\" \"+h.className+\" \").replace(/[\\t\\n\\r]/g,\" \").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,\"\")},TAG:function(a,b){return a[1].replace(j,\"\").toLowerCase()},CHILD:function(a){if(a[1]===\"nth\"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\\+|\\s*/g,\"\");var b=/(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(a[2]===\"even\"&&\"2n\"||a[2]===\"odd\"&&\"2n+1\"||!/\\D/.test(a[2])&&\"0n+\"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,\"\");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||\"\").replace(j,\"\"),a[2]===\"~=\"&&(a[4]=\" \"+a[4]+\" \");return a},PSEUDO:function(b,c,d,e,f){if(b[1]===\"not\")if((a.exec(b[3])||\"\").length>1||/^\\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!==\"hidden\"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute(\"type\"),c=a.type;return a.nodeName.toLowerCase()===\"input\"&&\"text\"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"radio\"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"checkbox\"===a.type},file:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"file\"===a.type},password:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"password\"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"submit\"===a.type},image:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"image\"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"reset\"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b===\"input\"&&\"button\"===a.type||b===\"button\"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e===\"contains\")return(a.textContent||a.innerText||n([a])||\"\").indexOf(b[3])>=0;if(e===\"not\"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case\"only\":case\"first\":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k===\"first\")return!0;l=a;case\"last\":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case\"nth\":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute(\"id\")===b},TAG:function(a,b){return b===\"*\"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(\" \"+(a.className||a.getAttribute(\"class\"))+\" \").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+\"\",f=b[2],g=b[4];return d==null?f===\"!=\":!f&&m.attr?d!=null:f===\"=\"?e===g:f===\"*=\"?e.indexOf(g)>=0:f===\"~=\"?(\" \"+e+\" \").indexOf(g)>=0:g?f===\"!=\"?e!==g:f===\"^=\"?e.indexOf(g)===0:f===\"$=\"?e.substr(e.length-g.length)===g:f===\"|=\"?e===g||e.substr(0,g.length+1)===g+\"-\":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return\"\\\\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\\[]*\\])(?![^\\(]*\\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\\r|\\n)*?)/.source+o.match[r].source.replace(/\\\\(\\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)===\"[object Array]\")Array.prototype.push.apply(d,a);else if(typeof a.length==\"number\")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement(\"div\"),d=\"script\"+(new Date).getTime(),e=c.documentElement;a.innerHTML=\"<a name='\"+d+\"'/>\",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!=\"undefined\"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=\"undefined\"&&e.getAttributeNode(\"id\").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=\"undefined\"&&a.getAttributeNode(\"id\");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement(\"div\");a.appendChild(c.createComment(\"\")),a.getElementsByTagName(\"*\").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]===\"*\"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML=\"<a href='#'></a>\",a.firstChild&&typeof a.firstChild.getAttribute!=\"undefined\"&&a.firstChild.getAttribute(\"href\")!==\"#\"&&(o.attrHandle.href=function(a){return a.getAttribute(\"href\",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement(\"div\"),d=\"__sizzle__\";b.innerHTML=\"<p class='TEST'></p>\";if(!b.querySelectorAll||b.querySelectorAll(\".TEST\").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b===\"body\"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!==\"object\"){var k=e,l=e.getAttribute(\"id\"),n=l||d,p=e.parentNode,q=/^\\s*[+~]/.test(b);l?n=n.replace(/'/g,\"\\\\$&\"):e.setAttribute(\"id\",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll(\"[id='\"+n+\"'] \"+b),f)}catch(r){}finally{l||k.removeAttribute(\"id\")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement(\"div\"),\"div\"),e=!1;try{b.call(c.documentElement,\"[test!='']:sizzle\")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g,\"='$1']\");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement(\"div\");a.innerHTML=\"<div class='test e'></div><div class='test'></div>\";if(!!a.getElementsByClassName&&a.getElementsByClassName(\"e\").length!==0){a.lastChild.className=\"e\";if(a.getElementsByClassName(\"e\").length===1)return;o.order.splice(1,0,\"CLASS\"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=\"undefined\"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!==\"HTML\":!1};var y=function(a,b,c){var d,e=[],f=\"\",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,\"\");a=o.relative[a]?a+\"*\":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[\":\"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\\[\\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!=\"string\")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack(\"\",\"find\",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),\"not\",a)},filter:function(a){return this.pushStack(T(this,a,!0),\"filter\",a)},is:function(a){return!!a&&(typeof a==\"string\"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!=\"string\"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,\"closest\",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a==\"string\")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==\"string\"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return f.dir(a,\"parentNode\",c)},next:function(a){return f.nth(a,2,\"nextSibling\")},prev:function(a){return f.nth(a,2,\"previousSibling\")},nextAll:function(a){return f.dir(a,\"nextSibling\")},prevAll:function(a){return f.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return f.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return f.dir(a,\"previousSibling\",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,\"iframe\")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d==\"string\"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(\",\"))}}),f.extend({filter:function(a,b,c){c&&(a=\":not(\"+a+\")\");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",W=/ jQuery\\d+=\"(?:\\d+|null)\"/g,X=/^\\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,Z=/<([\\w:]+)/,$=/<tbody/i,_=/<|&#?\\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp(\"<(?:\"+V+\")[\\\\s/>]\",\"i\"),bd=/checked\\s*(?:[^=]|=\\s*.checked.)/i,be=/\\/(java|ecma)script/i,bf=/^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,bg={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],area:[1,\"<map>\",\"</map>\"],_default:[0,\"\",\"\"]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,\"div<div>\",\"</div>\"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,\"body\")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f\n.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,\"before\",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,\"after\",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName(\"*\")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName(\"*\"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,\"\"):null;if(typeof a==\"string\"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(Y,\"<$1></$2>\");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName(\"*\")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!=\"string\"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),\"replaceWith\",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j==\"string\"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,\"tr\");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:\"GET\",global:!1,url:b.src,async:!1,dataType:\"script\"}):f.globalEval((b.text||b.textContent||b.innerHTML||\"\").replace(bf,\"/*$0*/\")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j==\"string\"&&j.length<512&&i===c&&j.charAt(0)===\"<\"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test(\"<\"+a.nodeName+\">\")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement==\"undefined\"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l==\"number\"&&(l+=\"\");if(!l)continue;if(typeof l==\"string\")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,\"<$1></$2>\");var m=(Z.exec(l)||[\"\",\"\"])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement(\"div\"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m===\"table\"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===\"<table>\"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],\"tbody\")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)==\"number\")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,\"script\")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName(\"script\"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\\([^)]*\\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\\-+]?(?:\\d*\\.)?\\d+$/i,bt=/^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,bu=/^([\\-+])=([\\-+.\\de]+)/,bv=/^margin/,bw={position:\"absolute\",visibility:\"hidden\",display:\"block\"},bx=[\"Top\",\"Right\",\"Bottom\",\"Left\"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,\"opacity\");return c===\"\"?\"1\":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":f.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&\"get\"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h===\"string\"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h=\"number\");if(d==null||h===\"number\"&&isNaN(d))return;h===\"number\"&&!f.cssNumber[i]&&(d+=\"px\");if(!k||!(\"set\"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c===\"cssFloat\"&&(c=\"float\");if(g&&\"get\"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,\"-$1\").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===\"\"&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b===\"fontSize\"?\"1em\":f,f=g.pixelLeft+\"px\",g.left=c,d&&(a.runtimeStyle.left=d));return f===\"\"?\"auto\":f}),by=bz||bA,f.each([\"height\",\"width\"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+\"px\":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||\"\")?parseFloat(RegExp.$1)/100+\"\":b?\"1\":\"\"},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?\"alpha(opacity=\"+b*100+\")\":\"\",g=d&&d.filter||c.filter||\"\";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,\"\"))===\"\"){c.removeAttribute(\"filter\");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+\" \"+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:\"inline-block\"},function(){return b?by(a,\"margin-right\"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,\"display\"))===\"none\"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c==\"string\"?c.split(\" \"):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\\[\\]$/,bE=/\\r?\\n/g,bF=/#.*$/,bG=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\\/\\//,bL=/\\?/,bM=/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=[\"*/\"]+[\"*\"];try{bU=e.href}catch(bX){bU=c.createElement(\"a\"),bU.href=\"\",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!=\"string\"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(\" \");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h=\"GET\";c&&(f.isFunction(c)?(d=c,c=b):typeof c==\"object\"&&(c=f.param(c,f.ajaxSettings.traditional),h=\"POST\"));var i=this;f.ajax({url:a,type:h,dataType:\"html\",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f(\"<div>\").append(c.replace(bM,\"\")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,\"\\r\\n\")}}):{name:b.name,value:c.replace(bE,\"\\r\\n\")}}).get()}}),f.each(\"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split(\" \"),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each([\"get\",\"post\"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,\"script\")},getJSON:function(a,b,c){return f.get(a,b,c,\"json\")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:\"GET\",contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",processData:!0,async:!0,accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",text:\"text/plain\",json:\"application/json, text/javascript\",\"*\":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\"},converters:{\"* text\":a.String,\"text html\":!0,\"text json\":f.parseJSON,\"text xml\":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||\"\",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader(\"Last-Modified\"))f.lastModified[k]=y;if(z=v.getResponseHeader(\"Etag\"))f.etag[k]=z}if(a===304)w=\"notmodified\",o=!0;else try{r=cb(d,x),w=\"success\",o=!0}catch(A){w=\"parsererror\",u=A}}else{u=w;if(!w||a)w=\"error\",a<0&&(a=0)}v.status=a,v.statusText=\"\"+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger(\"ajax\"+(o?\"Success\":\"Error\"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger(\"ajaxComplete\",[v,d]),--f.active||f.event.trigger(\"ajaxStop\"))}}typeof a==\"object\"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks(\"once memory\"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||\"abort\",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+\"\").replace(bF,\"\").replace(bK,bV[1]+\"//\"),d.dataTypes=f.trim(d.dataType||\"*\").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]===\"http:\"?80:443))==(bV[3]||(bV[1]===\"http:\"?80:443)))),d.data&&d.processData&&typeof d.data!=\"string\"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger(\"ajaxStart\");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?\"&\":\"?\")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,\"$1_=\"+x);d.url=y+(y===d.url?(bL.test(d.url)?\"&\":\"?\")+\"_=\"+x:\"\")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader(\"Content-Type\",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader(\"If-Modified-Since\",f.lastModified[k]),f.etag[k]&&v.setRequestHeader(\"If-None-Match\",f.etag[k])),v.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!==\"*\"?\", \"+bW+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,\"No Transport\");else{v.readyState=1,t&&g.trigger(\"ajaxSend\",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort(\"timeout\")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join(\"&\").replace(bC,\"+\")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\\=)\\?(&|$)|\\?\\?/i;f.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){return f.expando+\"_\"+cc++}}),f.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e=typeof b.data==\"string\"&&/^application\\/x\\-www\\-form\\-urlencoded/.test(b.contentType);if(b.dataTypes[0]===\"jsonp\"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l=\"$1\"+h+\"$2\";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\\?/.test(j)?\"&\":\"?\")+b.jsonp+\"=\"+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters[\"script json\"]=function(){g||f.error(h+\" was not called\");return g[0]},b.dataTypes[0]=\"json\";return\"script\"}}),f.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/javascript|ecmascript/},converters:{\"text script\":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter(\"script\",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\",a.global=!1)}),f.ajaxTransport(\"script\",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName(\"head\")[0]||c.documentElement;return{send:function(f,g){d=c.createElement(\"script\"),d.async=\"async\",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,\"success\")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&\"withCredentials\"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e[\"X-Requested-With\"]&&(e[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=\"\"}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,co,cp=[[\"height\",\"marginTop\",\"marginBottom\",\"paddingTop\",\"paddingBottom\"],[\"width\",\"marginLeft\",\"marginRight\",\"paddingLeft\",\"paddingRight\"],[\"opacity\"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct(\"show\",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,\"olddisplay\")&&e===\"none\"&&(e=d.style.display=\"\"),(e===\"\"&&f.css(d,\"display\")===\"none\"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,\"olddisplay\",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===\"\"||e===\"none\")d.style.display=f._data(d,\"olddisplay\")||\"\"}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct(\"hide\",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,\"display\"),e!==\"none\"&&!f._data(d,\"olddisplay\")&&f._data(d,\"olddisplay\",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display=\"none\");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a==\"boolean\";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(\":hidden\");f(this)[b?\"show\":\"hide\"]()}):this.animate(ct(\"toggle\",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(\":hidden\").css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(\":hidden\"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&\"expand\"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||\"swing\";if(h===\"hide\"&&d||h===\"show\"&&!d)return b.complete.call(this);c&&(g===\"height\"||g===\"width\")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,\"display\")===\"inline\"&&f.css(this,\"float\")===\"none\"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)===\"inline\"?this.style.display=\"inline-block\":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow=\"hidden\");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,\"toggle\"+i)||(h===\"toggle\"?d?\"show\":\"hide\":0),q?(f._data(this,\"toggle\"+i,q===\"show\"?\"hide\":\"show\"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?\"\":\"px\"),p!==\"px\"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]===\"-=\"?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,\"\"));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!=\"string\"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||\"fx\",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(\".run\")===b.length-4&&h(this,g,b);else g[b=a+\".run\"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct(\"show\",1),slideUp:ct(\"hide\",1),slideToggle:ct(\"toggle\",1),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a==\"object\"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration==\"number\"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue=\"fx\";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b===\"auto\"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?\"\":\"px\"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,\"fxshow\"+e.prop)===b&&(e.options.hide?f._data(e.elem,\"fxshow\"+e.prop,e.start):e.options.show&&f._data(e.elem,\"fxshow\"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,\"fxshow\"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop===\"width\"||this.prop===\"height\"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,\"fxshow\"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each([\"\",\"X\",\"Y\"],function(a,b){h.style[\"overflow\"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,\"fxshow\"+b,!0),f.removeData(h,\"toggle\"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,\"opacity\",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf(\"margin\")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;\"getBoundingClientRect\"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position===\"fixed\")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!==\"visible\"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position===\"relative\"||j.position===\"static\")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position===\"fixed\"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,\"marginTop\"))||0,c+=parseFloat(f.css(a,\"marginLeft\"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,\"position\");d===\"static\"&&(a.style.position=\"relative\");var e=f(a),g=e.offset(),h=f.css(a,\"top\"),i=f.css(a,\"left\"),j=(d===\"absolute\"||d===\"fixed\")&&f.inArray(\"auto\",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),\"using\"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,\"marginTop\"))||0,c.left-=parseFloat(f.css(a,\"marginLeft\"))||0,d.top+=parseFloat(f.css(b[0],\"borderTopWidth\"))||0,d.left+=parseFloat(f.css(b[0],\"borderLeftWidth\"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,\"position\")===\"static\")a=a.offsetParent;return a})}}),f.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:\"height\",Width:\"width\"},function(a,c){var d=\"client\"+a,e=\"scroll\"+a,g=\"offset\"+a;f.fn[\"inner\"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,\"padding\")):this[c]():null},f.fn[\"outer\"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?\"margin\":\"border\")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define==\"function\"&&define.amd&&define.amd.jQuery&&define(\"jquery\",[],function(){return f})})(window);"
  },
  {
    "path": "extra/loader.coffee",
    "content": "fs = {}\n\nmakeURL = (blob) ->\n    return URL.createObjectURL blob\n\nmakeBlob = (data, type) ->\n    #builder = new BlobBuilder()\n    #builder.append(data)\n    #blob = builder.getBlob(type)\n    #is recommended, but doesn't work in either Firefox or Chrome o_O\n    blob = new Blob([data], type:type)\n    return blob\n\nwindow.getURL = (data, mime) ->\n    blob = makeBlob data, mime\n    return makeURL blob\n\nresolvePath = (base, path) ->\n    if path[0] == '/'\n        return path\n    else\n        path = path.split '/'\n        if base == '/'\n            base = ['']\n        else\n            base = base.split '/'\n\n        while base.length > 0 and path.length > 0 and path[0] == '..'\n            base.pop()\n            path.shift()\n\n        if base.length == 0 || path.length == 0 || base[0] != ''\n            throw \"Invalid path: #{base.join '/'}/#{path.join '/'}\"\n        return \"#{base.join('/')}/#{path.join('/')}\"\n\ngetJSON = (url, callback) ->\n    request = new XMLHttpRequest()\n    request.open 'GET', url, true\n    request.onload = ->\n        callback(JSON.parse(request.response))\n    request.send()\n\ngetBuffer = (url, progress, callback) ->\n    request = new XMLHttpRequest()\n    request.open 'GET', url, true\n    request.responseType = 'arraybuffer'\n    request.onload = ->\n        callback(request.response)\n    request.onprogress = (event) ->\n        if event.lengthComputable\n            progress event.loaded/event.total\n    request.send()\n\nisImage = (path) ->\n    return path.match('\\.jpg$|\\.jpeg|\\.gif$|\\.png')\n\nwindow.loader =\n    resolvePath: resolvePath\n    main: ->\n        main = @require 'main'\n        if main.main\n            main.main()\n        else\n            throw 'Main function is not defined in main module.'\n\n    define: (path, code) ->\n        dirname = path.split '/'\n        dirname.pop()\n        dirname = dirname.join '/'\n\n        require = (modpath) ->\n            abspath = resolvePath dirname, modpath\n            node = fs[\"#{abspath}.js\"]\n            if not node\n                node = fs[\"#{abspath}/module.js\"]\n            if not node then throw \"Module not found: #{abspath}\"\n            if !node.value then node.create()\n            return node.value\n\n        get = (respath) ->\n            abspath = resolvePath dirname, respath\n            node = fs[abspath]\n            if not node then throw \"Resource not found: #{abspath}\"\n            return node\n\n        get.exists = (respath) ->\n            abspath = resolvePath dirname, respath\n            node = fs[abspath]\n            return node != undefined\n\n        folder = get.folder = (folderpath) ->\n            folder_abs = resolvePath dirname, folderpath\n            return {\n                path: folder_abs,\n                name: folder_abs.split('/')[folder_abs.split('/').length-1]\n                get: (respath) ->\n                    nodepath = resolvePath folder_abs, respath\n                    node = fs[nodepath]\n                    if not node then throw \"Resource not found: #{nodepath}\"\n                    return node\n\n                exists: (respath) ->\n                    nodepath = resolvePath folder_abs, respath\n                    return fs[nodepath] != undefined\n                    \n                listdir: (respath) ->\n                    if respath then nodepath = resolvepath folder_abs, respath\n                    else nodepath = folder_abs\n\n                    result = []\n                    for name of fs\n                        match = name.match \"#{folder_abs}/[a-zA-Z0-9-\\.]+\"\n                        if match\n                            match = match[0]\n                            if result.indexOf(match) == -1\n                                result.push match\n\n                    translated = []\n                    for name in result\n                        if name.match /\\.[a-z]+$/\n                            translated.push name\n                        else\n                            translated.push folder name\n                    return translated\n            }\n\n        get.listdir = (respath, match) ->\n            if respath\n                abspath = resolvePath dirname, respath\n            else\n                abspath = dirname\n\n            result = []\n            for name of fs\n                if name.search(abspath) == 0\n                    if match\n                        if name.match match\n                            result.push name\n                    else\n                        result.push name\n            return result\n\n        fs[path] =\n            path: path\n            type: 'code'\n            data: code\n            create: ->\n                @value = {}\n                retval = code @value, require, get\n                if retval\n                    @value = retval\n\n    require: (modpath) ->\n        abspath = resolvePath '/', modpath\n        node = fs[\"#{abspath}.js\"]\n        if not node\n            node = fs[\"#{abspath}/module.js\"]\n\n        if not node then throw \"Module not found: #{abspath}\"\n        if !node.value then node.create()\n        return node.value\n\n    loadPack: ({url, progress, loaded}) ->\n        files = {}\n        hooks = @hooks\n        getBuffer url, ((factor) -> if progress then progress(factor*0.5, 'network')), (data) ->\n            decoding = 0\n            decoded = 0\n\n            doLoad = (name, info) ->\n                if typeof info == 'object' and info.offset != undefined and info.size != undefined\n                    storage = new ArrayBuffer info.size\n                    dst = new Uint8Array storage\n                    src = new Uint8Array data, 8+length+info.offset, info.size\n                    dst.set src\n                    dst = dst.buffer\n\n                    if hooks\n                        for matcher, decode of hooks\n                            if name.match(matcher)\n                                decoding += 1\n                                decode name, dst, (result) ->\n                                    decoded += 1\n                                    files[name] = result\n                                    if progress then progress(0.5+(decoded/decoding)*0.5, 'decode')\n                                    if decoding == decoded and loaded then loaded(files)\n                                return\n                    files[name] = dst\n                else\n                    if hooks\n                        for matcher, decode of hooks\n                            if name.match(matcher)\n                                decode name, info, (result) ->\n                                    files[name] = result\n                                return\n                    files[name] = info\n\n            length = new Uint32Array(data, 4, 1)[0]\n            metadata = new Uint8Array(data, 8, length)\n            result = ''\n            for i in [0...length]\n                result += String.fromCharCode(metadata[i])\n            result = JSON.parse(result)\n\n            for name, info of result\n                doLoad name, info, data\n\n            if decoding == decoded and loaded then loaded(files)\n\n    hooks: (@hooks) -> return @\n\n    mount: ({url, mountpoint, progress, loaded}) ->\n        mountpoint ?= '/'\n        @loadPack url: url, progress: progress, loaded: (data) ->\n            for name, value of data\n                fs[name] = value\n            loaded(data, fs)\n"
  },
  {
    "path": "extra/loader.js",
    "content": "// Generated by CoffeeScript 1.3.3\n(function() {\n  var fs, getBuffer, getJSON, isImage, makeBlob, makeURL, resolvePath;\n\n  fs = {};\n\n  makeURL = function(blob) {\n    return URL.createObjectURL(blob);\n  };\n\n  makeBlob = function(data, type) {\n    var blob;\n    blob = new Blob([data], {\n      type: type\n    });\n    return blob;\n  };\n\n  window.getURL = function(data, mime) {\n    var blob;\n    blob = makeBlob(data, mime);\n    return makeURL(blob);\n  };\n\n  resolvePath = function(base, path) {\n    if (path[0] === '/') {\n      return path;\n    } else {\n      path = path.split('/');\n      if (base === '/') {\n        base = [''];\n      } else {\n        base = base.split('/');\n      }\n      while (base.length > 0 && path.length > 0 && path[0] === '..') {\n        base.pop();\n        path.shift();\n      }\n      if (base.length === 0 || path.length === 0 || base[0] !== '') {\n        throw \"Invalid path: \" + (base.join('/')) + \"/\" + (path.join('/'));\n      }\n      return \"\" + (base.join('/')) + \"/\" + (path.join('/'));\n    }\n  };\n\n  getJSON = function(url, callback) {\n    var request;\n    request = new XMLHttpRequest();\n    request.open('GET', url, true);\n    request.onload = function() {\n      return callback(JSON.parse(request.response));\n    };\n    return request.send();\n  };\n\n  getBuffer = function(url, progress, callback) {\n    var request;\n    request = new XMLHttpRequest();\n    request.open('GET', url, true);\n    request.responseType = 'arraybuffer';\n    request.onload = function() {\n      return callback(request.response);\n    };\n    request.onprogress = function(event) {\n      if (event.lengthComputable) {\n        return progress(event.loaded / event.total);\n      }\n    };\n    return request.send();\n  };\n\n  isImage = function(path) {\n    return path.match('\\.jpg$|\\.jpeg|\\.gif$|\\.png');\n  };\n\n  window.loader = {\n    resolvePath: resolvePath,\n    main: function() {\n      var main;\n      main = this.require('main');\n      if (main.main) {\n        return main.main();\n      } else {\n        throw 'Main function is not defined in main module.';\n      }\n    },\n    define: function(path, code) {\n      var dirname, folder, get, require;\n      dirname = path.split('/');\n      dirname.pop();\n      dirname = dirname.join('/');\n      require = function(modpath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, modpath);\n        node = fs[\"\" + abspath + \".js\"];\n        if (!node) {\n          node = fs[\"\" + abspath + \"/module.js\"];\n        }\n        if (!node) {\n          throw \"Module not found: \" + abspath;\n        }\n        if (!node.value) {\n          node.create();\n        }\n        return node.value;\n      };\n      get = function(respath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, respath);\n        node = fs[abspath];\n        if (!node) {\n          throw \"Resource not found: \" + abspath;\n        }\n        return node;\n      };\n      get.exists = function(respath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, respath);\n        node = fs[abspath];\n        return node !== void 0;\n      };\n      folder = get.folder = function(folderpath) {\n        var folder_abs;\n        folder_abs = resolvePath(dirname, folderpath);\n        return {\n          path: folder_abs,\n          name: folder_abs.split('/')[folder_abs.split('/').length - 1],\n          get: function(respath) {\n            var node, nodepath;\n            nodepath = resolvePath(folder_abs, respath);\n            node = fs[nodepath];\n            if (!node) {\n              throw \"Resource not found: \" + nodepath;\n            }\n            return node;\n          },\n          exists: function(respath) {\n            var nodepath;\n            nodepath = resolvePath(folder_abs, respath);\n            return fs[nodepath] !== void 0;\n          },\n          listdir: function(respath) {\n            var match, name, nodepath, result, translated, _i, _len;\n            if (respath) {\n              nodepath = resolvepath(folder_abs, respath);\n            } else {\n              nodepath = folder_abs;\n            }\n            result = [];\n            for (name in fs) {\n              match = name.match(\"\" + folder_abs + \"/[a-zA-Z0-9-\\.]+\");\n              if (match) {\n                match = match[0];\n                if (result.indexOf(match) === -1) {\n                  result.push(match);\n                }\n              }\n            }\n            translated = [];\n            for (_i = 0, _len = result.length; _i < _len; _i++) {\n              name = result[_i];\n              if (name.match(/\\.[a-z]+$/)) {\n                translated.push(name);\n              } else {\n                translated.push(folder(name));\n              }\n            }\n            return translated;\n          }\n        };\n      };\n      get.listdir = function(respath, match) {\n        var abspath, name, result;\n        if (respath) {\n          abspath = resolvePath(dirname, respath);\n        } else {\n          abspath = dirname;\n        }\n        result = [];\n        for (name in fs) {\n          if (name.search(abspath) === 0) {\n            if (match) {\n              if (name.match(match)) {\n                result.push(name);\n              }\n            } else {\n              result.push(name);\n            }\n          }\n        }\n        return result;\n      };\n      return fs[path] = {\n        path: path,\n        type: 'code',\n        data: code,\n        create: function() {\n          var retval;\n          this.value = {};\n          retval = code(this.value, require, get);\n          if (retval) {\n            return this.value = retval;\n          }\n        }\n      };\n    },\n    require: function(modpath) {\n      var abspath, node;\n      abspath = resolvePath('/', modpath);\n      node = fs[\"\" + abspath + \".js\"];\n      if (!node) {\n        node = fs[\"\" + abspath + \"/module.js\"];\n      }\n      if (!node) {\n        throw \"Module not found: \" + abspath;\n      }\n      if (!node.value) {\n        node.create();\n      }\n      return node.value;\n    },\n    loadPack: function(_arg) {\n      var files, hooks, loaded, progress, url;\n      url = _arg.url, progress = _arg.progress, loaded = _arg.loaded;\n      files = {};\n      hooks = this.hooks;\n      return getBuffer(url, (function(factor) {\n        if (progress) {\n          return progress(factor * 0.5, 'network');\n        }\n      }), function(data) {\n        var decoded, decoding, doLoad, i, info, length, metadata, name, result, _i;\n        decoding = 0;\n        decoded = 0;\n        doLoad = function(name, info) {\n          var decode, dst, matcher, src, storage;\n          if (typeof info === 'object' && info.offset !== void 0 && info.size !== void 0) {\n            storage = new ArrayBuffer(info.size);\n            dst = new Uint8Array(storage);\n            src = new Uint8Array(data, 8 + length + info.offset, info.size);\n            dst.set(src);\n            dst = dst.buffer;\n            if (hooks) {\n              for (matcher in hooks) {\n                decode = hooks[matcher];\n                if (name.match(matcher)) {\n                  decoding += 1;\n                  decode(name, dst, function(result) {\n                    decoded += 1;\n                    files[name] = result;\n                    if (progress) {\n                      progress(0.5 + (decoded / decoding) * 0.5, 'decode');\n                    }\n                    if (decoding === decoded && loaded) {\n                      return loaded(files);\n                    }\n                  });\n                  return;\n                }\n              }\n            }\n            return files[name] = dst;\n          } else {\n            if (hooks) {\n              for (matcher in hooks) {\n                decode = hooks[matcher];\n                if (name.match(matcher)) {\n                  decode(name, info, function(result) {\n                    return files[name] = result;\n                  });\n                  return;\n                }\n              }\n            }\n            return files[name] = info;\n          }\n        };\n        length = new Uint32Array(data, 4, 1)[0];\n        metadata = new Uint8Array(data, 8, length);\n        result = '';\n        for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {\n          result += String.fromCharCode(metadata[i]);\n        }\n        result = JSON.parse(result);\n        for (name in result) {\n          info = result[name];\n          doLoad(name, info, data);\n        }\n        if (decoding === decoded && loaded) {\n          return loaded(files);\n        }\n      });\n    },\n    hooks: function(hooks) {\n      this.hooks = hooks;\n      return this;\n    },\n    mount: function(_arg) {\n      var loaded, mountpoint, progress, url;\n      url = _arg.url, mountpoint = _arg.mountpoint, progress = _arg.progress, loaded = _arg.loaded;\n      if (mountpoint == null) {\n        mountpoint = '/';\n      }\n      return this.loadPack({\n        url: url,\n        progress: progress,\n        loaded: function(data) {\n          var name, value;\n          for (name in data) {\n            value = data[name];\n            fs[name] = value;\n          }\n          return loaded(data, fs);\n        }\n      });\n    }\n  };\n\n}).call(this);\n"
  },
  {
    "path": "extra/matrix.coffee",
    "content": "pi = Math.PI\ntau = 2*pi\ndeg = 360/tau\narc = tau/360\n\nwindow.Mat3 = class Mat3\n    constructor: (@data) ->\n        @data ?= new Float32Array 9\n        @identity()\n    \n    identity: ->\n        d = @data\n        d[0]  = 1; d[1]  =0; d[2]  = 0\n        d[3]  = 0; d[4]  =1; d[5]  = 0\n        d[6]  = 0; d[7]  =0; d[8]  = 1\n        return @\n\n    transpose: ->\n        d = @data\n        a01 = d[1]; a02 = d[2]; a12 = d[5]\n\n        d[1] = d[3]\n        d[2] = d[6]\n        d[3] = a01\n        d[5] = d[7]\n        d[6] = a02\n        d[7] = a12\n        return @\n   \n    mulVec3: (vec, dst=vec) ->\n        @mulVal3 vec.x, vec.y, vec.z, dst\n        return dst\n\n    mulVal3: (x, y, z, dst) ->\n        dst = dst.data\n        d = @data\n        dst[0] = d[0]*x + d[3]*y + d[6]*z\n        dst[1] = d[1]*x + d[4]*y + d[7]*z\n        dst[2] = d[2]*x + d[5]*y + d[8]*z\n\n        return @\n\n    rotatex: (angle) ->\n        s = Math.sin angle*arc\n        c = Math.cos angle*arc\n        return @amul(\n             1,  0,  0,\n             0,  c,  s,\n             0, -s,  c\n        )\n    \n    rotatey: (angle) ->\n        s = Math.sin angle*arc\n        c = Math.cos angle*arc\n        return @amul(\n             c,  0, -s,\n             0,  1,  0,\n             s,  0,  c\n        )\n    \n    rotatez: (angle) ->\n        s = Math.sin angle*arc\n        c = Math.cos angle*arc\n        return @amul(\n             c,  s,  0,\n            -s,  c,  0,\n             0,  0,  1\n        )\n       \n    amul: (\n        b00, b10, b20,\n        b01, b11, b21,\n        b02, b12, b22,\n        b03, b13, b23\n    ) ->\n        a = @data\n\n        a00 = a[0]\n        a10 = a[1]\n        a20 = a[2]\n        \n        a01 = a[3]\n        a11 = a[4]\n        a21 = a[5]\n        \n        a02 = a[6]\n        a12 = a[7]\n        a22 = a[8]\n        \n        a[0]  = a00*b00 + a01*b10 + a02*b20\n        a[1]  = a10*b00 + a11*b10 + a12*b20\n        a[2]  = a20*b00 + a21*b10 + a22*b20\n        \n        a[3]  = a00*b01 + a01*b11 + a02*b21\n        a[4]  = a10*b01 + a11*b11 + a12*b21\n        a[5]  = a20*b01 + a21*b11 + a22*b21\n        \n        a[6]  = a00*b02 + a01*b12 + a02*b22\n        a[7]  = a10*b02 + a11*b12 + a12*b22\n        a[8]  = a20*b02 + a21*b12 + a22*b22\n\n        return @\n\n    log: ->\n        d = @data\n        console.log '%f, %f, %f,\\n%f, %f, %f, \\n%f, %f, %f, ', d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]\n\nwindow.Mat4 = class Mat4\n    constructor: (@data) ->\n        @data ?= new Float32Array 16\n        @identity()\n\n    identity: ->\n        d = @data\n        d[0]  = 1; d[1]  =0; d[2]  = 0; d[3]  = 0\n        d[4]  = 0; d[5]  =1; d[6]  = 0; d[7]  = 0\n        d[8]  = 0; d[9]  =0; d[10] = 1; d[11] = 0\n        d[12] = 0; d[13] =0; d[14] = 0; d[15] = 1\n        return @\n\n    zero: ->\n        d = @data\n        d[0]  = 0; d[1]  =0; d[2]  = 0; d[3]  = 0\n        d[4]  = 0; d[5]  =0; d[6]  = 0; d[7]  = 0\n        d[8]  = 0; d[9]  =0; d[10] = 0; d[11] = 0\n        d[12] = 0; d[13] =0; d[14] = 0; d[15] = 0\n        return @\n\n    copy: (dest) ->\n        src = @data\n        dst = dest.data\n        dst[0] = src[0]\n        dst[1] = src[1]\n        dst[2] = src[2]\n        dst[3] = src[3]\n        dst[4] = src[4]\n        dst[5] = src[5]\n        dst[6] = src[6]\n        dst[7] = src[7]\n        dst[8] = src[8]\n        dst[9] = src[9]\n        dst[10] = src[10]\n        dst[11] = src[11]\n        dst[12] = src[12]\n        dst[13] = src[13]\n        dst[14] = src[14]\n        dst[15] = src[15]\n        return dest\n\n    toMat3: (dest) ->\n        src = @data\n        dst = dest.data\n        dst[0] = src[0]\n        dst[1] = src[1]\n        dst[2] = src[2]\n        dst[3] = src[4]\n        dst[4] = src[5]\n        dst[5] = src[6]\n        dst[6] = src[8]\n        dst[7] = src[9]\n        dst[8] = src[10]\n        \n        return dest\n\n    toMat3Rot: (dest) ->\n        dst = dest.data\n        src = @data\n        a00 = src[0]; a01 = src[1]; a02 = src[2]\n        a10 = src[4]; a11 = src[5]; a12 = src[6]\n        a20 = src[8]; a21 = src[9]; a22 = src[10]\n\n        b01 = a22 * a11 - a12 * a21\n        b11 = -a22 * a10 + a12 * a20\n        b21 = a21 * a10 - a11 * a20\n\n        d = a00 * b01 + a01 * b11 + a02 * b21\n        id = 1 / d\n\n        dst[0] = b01 * id\n        dst[3] = (-a22 * a01 + a02 * a21) * id\n        dst[6] = (a12 * a01 - a02 * a11) * id\n        dst[1] = b11 * id\n        dst[4] = (a22 * a00 - a02 * a20) * id\n        dst[7] = (-a12 * a00 + a02 * a10) * id\n        dst[2] = b21 * id\n        dst[5] = (-a21 * a00 + a01 * a20) * id\n        dst[8] = (a11 * a00 - a01 * a10) * id\n\n        return dest\n\n    perspective: (fov, aspect, near, far) ->\n        @zero()\n        d = @data\n        top = near * Math.tan(fov*Math.PI/360)\n        right = top*aspect\n        left = -right\n        bottom = -top\n\n        d[0] = (2*near)/(right-left)\n        d[5] = (2*near)/(top-bottom)\n        d[8] = (right+left)/(right-left)\n        d[9] = (top+bottom)/(top-bottom)\n        d[10] = -(far+near)/(far-near)\n        d[11] = -1\n        d[14] = -(2*far*near)/(far-near)\n       \n        return @\n        \n    inversePerspective: (fov, aspect, near, far) ->\n        @zero()\n        dst = @data\n        top = near * Math.tan(fov*Math.PI/360)\n        right = top*aspect\n        left = -right\n        bottom = -top\n\n        dst[0] = (right-left)/(2*near)\n        dst[5] = (top-bottom)/(2*near)\n        dst[11] = -(far-near)/(2*far*near)\n        dst[12] = (right+left)/(2*near)\n        dst[13] = (top+bottom)/(2*near)\n        dst[14] = -1\n        dst[15] = (far+near)/(2*far*near)\n\n        return @\n       \n    ortho: (near=-1, far=1, top=-1, bottom=1, left=-1, right=1) ->\n        rl = right-left\n        tb = top - bottom\n        fn = far - near\n\n        return @set(\n            2/rl,   0,      0,      -(left+right)/rl,\n            0,      2/tb,   0,      -(top+bottom)/tb,\n            0,      0,      -2/fn,  -(far+near)/fn,\n            0,      0,      0,      1,\n        )\n        \n    inverseOrtho: (near=-1, far=1, top=-1, bottom=1, left=-1, right=1) ->\n        a = (right-left)/2\n        b = (right+left)/2\n        c = (top-bottom)/2\n        d = (top+bottom)/2\n        e = (far-near)/-2\n        f = (near+far)/2\n        g = 1\n\n        return @set(\n            a, 0, 0, b,\n            0, c, 0, d,\n            0, 0, e, f,\n            0, 0, 0, g\n        )\n\n    fromRotationTranslation: (quat, vec) ->\n        x = quat.x; y = quat.y; z = quat.z; w = quat.w\n        x2 = x + x\n        y2 = y + y\n        z2 = z + z\n\n        xx = x * x2\n        xy = x * y2\n        xz = x * z2\n        yy = y * y2\n        yz = y * z2\n        zz = z * z2\n        wx = w * x2\n        wy = w * y2\n        wz = w * z2\n\n        dest = @data\n       \n        ''' \n        dest[0] = 1 - 2.0 * y * y - 2.0 * y * y\n        dest[1] = 2 * x * y - 2.0 * w * z\n        dest[3] = 2 * x * z + 2.0 * w * y\n        \n        dest[4] = 2 * x * y + 2.0 * w * z\n        dest[5] = 1 - 2.0 * x * x - 2.0 * z * z\n        dest[6] = 2 * y * z - 2.0 * w * x\n\n        dest[8] = 2 * x * z - 2.0 * w * y\n        dest[9] = 2 * y * z + 2.0 * w * x\n        dest[10] = 1 - 2.0 * x * x - 2.0 * y * y\n        '''\n\n        '''\n        dest[0] = 1 - 2.0 * y * y - 2.0 * y * y\n        dest[1] = 2 * x * y + 2.0 * w * z\n        dest[2] = 2 * x * z - 2.0 * w * y\n\n        dest[4] = 2 * x * y - 2.0 * w * z\n        dest[5] = 1 - 2.0 * x * x - 2.0 * z * z\n        dest[6] = 2 * y * z + 2.0 * w * x\n\n        dest[8] = 2 * x * z + 2.0 * w * y\n        dest[9] = 2 * y * z - 2.0 * w * x\n        dest[10] = 1 - 2.0 * x * x - 2.0 * y * y\n        '''\n\n        dest[0] = 1 - (yy + zz)\n        dest[1] = xy + wz\n        dest[2] = xz - wy\n        dest[3] = 0\n        dest[4] = xy - wz\n        dest[5] = 1 - (xx + zz)\n        dest[6] = yz + wx\n        dest[7] = 0\n        dest[8] = xz + wy\n        dest[9] = yz - wx\n        dest[10] = 1 - (xx + yy)\n        dest[11] = 0\n        \n        dest[12] = vec.x\n        dest[13] = vec.y\n        dest[14] = vec.z\n        dest[15] = 1\n        \n        return @\n    \n    translateVec3: (vec) ->\n        return @translateVal3 vec.x, vec.y, vec.z\n\n    translateVal3: (x, y, z) ->\n        d = @data\n        a00 = d[0]; a01 = d[1]; a02 = d[2]; a03 = d[3]\n        a10 = d[4]; a11 = d[5]; a12 = d[6]; a13 = d[7]\n        a20 = d[8]; a21 = d[9]; a22 = d[10]; a23 = d[11]\n\n        d[12] = a00 * x + a10 * y + a20 * z + d[12]\n        d[13] = a01 * x + a11 * y + a21 * z + d[13]\n        d[14] = a02 * x + a12 * y + a22 * z + d[14]\n        d[15] = a03 * x + a13 * y + a23 * z + d[15]\n\n        return @\n\n    rotatex: (angle) ->\n        d = @data\n        rad = tau*(angle/360)\n        s = Math.sin rad\n        c = Math.cos rad\n\n        a10 = d[4]\n        a11 = d[5]\n        a12 = d[6]\n        a13 = d[7]\n        a20 = d[8]\n        a21 = d[9]\n        a22 = d[10]\n        a23 = d[11]\n\n        d[4] = a10 * c + a20 * s\n        d[5] = a11 * c + a21 * s\n        d[6] = a12 * c + a22 * s\n        d[7] = a13 * c + a23 * s\n\n        d[8] = a10 * -s + a20 * c\n        d[9] = a11 * -s + a21 * c\n        d[10] = a12 * -s + a22 * c\n        d[11] = a13 * -s + a23 * c\n\n        return @\n\n    rotatey: (angle) ->\n        d = @data\n        rad = tau*(angle/360)\n        s = Math.sin rad\n        c = Math.cos rad\n\n        a00 = d[0]\n        a01 = d[1]\n        a02 = d[2]\n        a03 = d[3]\n        a20 = d[8]\n        a21 = d[9]\n        a22 = d[10]\n        a23 = d[11]\n\n        d[0] = a00 * c + a20 * -s\n        d[1] = a01 * c + a21 * -s\n        d[2] = a02 * c + a22 * -s\n        d[3] = a03 * c + a23 * -s\n\n        d[8] = a00 * s + a20 * c\n        d[9] = a01 * s + a21 * c\n        d[10] = a02 * s + a22 * c\n        d[11] = a03 * s + a23 * c\n\n        return @\n    \n    rotatez: (angle) ->\n        d = @data\n        rad = tau*(angle/360)\n        s = Math.sin rad\n        c = Math.cos rad\n\n        a00 = d[0]\n        a01 = d[1]\n        a02 = d[2]\n        a03 = d[3]\n        a10 = d[4]\n        a11 = d[5]\n        a12 = d[6]\n        a13 = d[7]\n\n        d[0] = a00 * c + a10 * s\n        d[1] = a01 * c + a11 * s\n        d[2] = a02 * c + a12 * s\n        d[3] = a03 * c + a13 * s\n        d[4] = a00 * -s + a10 * c\n        d[5] = a01 * -s + a11 * c\n        d[6] = a02 * -s + a12 * c\n        d[7] = a03 * -s + a13 * c\n                 \n        return @\n\n    scale: (scalar) ->\n        d = @data\n\n        a00 = d[0]; a01 = d[1]; a02 = d[2]; a03 = d[3]\n        a10 = d[4]; a11 = d[5]; a12 = d[6]; a13 = d[7]\n        a20 = d[8]; a21 = d[9]; a22 = d[10]; a23 = d[11]\n\n        d[0] = a00 * scalar\n        d[1] = a01 * scalar\n        d[2] = a02 * scalar\n        d[3] = a03 * scalar\n\n        d[4] = a10 * scalar\n        d[5] = a11 * scalar\n        d[6] = a12 * scalar\n        d[7] = a13 * scalar\n\n        d[8] = a20 * scalar\n        d[9] = a21 * scalar\n        d[10] = a22 * scalar\n        d[11] = a23 * scalar\n        \n        return @\n\n    mulMat4: (other, dst=@) ->\n        dest = dst.data\n        mat = @data\n        mat2 = other.data\n\n        a00 = mat[ 0]; a01 = mat[ 1]; a02 = mat[ 2]; a03 = mat[3]\n        a10 = mat[ 4]; a11 = mat[ 5]; a12 = mat[ 6]; a13 = mat[7]\n        a20 = mat[ 8]; a21 = mat[ 9]; a22 = mat[10]; a23 = mat[11]\n        a30 = mat[12]; a31 = mat[13]; a32 = mat[14]; a33 = mat[15]\n\n        b0  = mat2[0]; b1 = mat2[1]; b2 = mat2[2]; b3 = mat2[3]\n        dest[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30\n        dest[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31\n        dest[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32\n        dest[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33\n\n        b0 = mat2[4]\n        b1 = mat2[5]\n        b2 = mat2[6]\n        b3 = mat2[7]\n        dest[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30\n        dest[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31\n        dest[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32\n        dest[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33\n\n        b0 = mat2[8]\n        b1 = mat2[9]\n        b2 = mat2[10]\n        b3 = mat2[11]\n        dest[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30\n        dest[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31\n        dest[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32\n        dest[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33\n\n        b0 = mat2[12]\n        b1 = mat2[13]\n        b2 = mat2[14]\n        b3 = mat2[15]\n        dest[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30\n        dest[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31\n        dest[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32\n        dest[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33\n\n        return dst\n   \n    mulVec3: (vec, dst=vec) ->\n        return @mulVal3 vec.x, vec.y, vec.z, dst\n\n    mulVal3: (x, y, z, dst) ->\n        dst = dst.data\n        d = @data\n        dst[0] = d[0]*x + d[4]*y + d[8] *z\n        dst[1] = d[1]*x + d[5]*y + d[9] *z\n        dst[2] = d[2]*x + d[6]*y + d[10]*z\n\n        return dst\n\n    mulVec4: (vec, dst) ->\n        dst ?= vec\n        return @mulVal4 vec.x, vec.y, vec.z, vec.w, dst\n\n    mulVal4: (x, y, z, w, dst) ->\n        dst = dst.data\n        d = @data\n        dst[0] = d[0]*x + d[4]*y + d[8] *z + d[12]*w\n        dst[1] = d[1]*x + d[5]*y + d[9] *z + d[13]*w\n        dst[2] = d[2]*x + d[6]*y + d[10]*z + d[14]*w\n        dst[3] = d[3]*x + d[7]*y + d[11]*z + d[15]*w\n\n        return dst\n\n    invert: (dst=@) ->\n        mat = @data\n        dest = dst.data\n\n        a00 = mat[0]; a01 = mat[1]; a02 = mat[2]; a03 = mat[3]\n        a10 = mat[4]; a11 = mat[5]; a12 = mat[6]; a13 = mat[7]\n        a20 = mat[8]; a21 = mat[9]; a22 = mat[10]; a23 = mat[11]\n        a30 = mat[12]; a31 = mat[13]; a32 = mat[14]; a33 = mat[15]\n\n        b00 = a00 * a11 - a01 * a10\n        b01 = a00 * a12 - a02 * a10\n        b02 = a00 * a13 - a03 * a10\n        b03 = a01 * a12 - a02 * a11\n        b04 = a01 * a13 - a03 * a11\n        b05 = a02 * a13 - a03 * a12\n        b06 = a20 * a31 - a21 * a30\n        b07 = a20 * a32 - a22 * a30\n        b08 = a20 * a33 - a23 * a30\n        b09 = a21 * a32 - a22 * a31\n        b10 = a21 * a33 - a23 * a31\n        b11 = a22 * a33 - a23 * a32\n\n        d = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06)\n            \n        if d==0 then return\n        invDet = 1 / d\n\n        dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet\n        dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet\n        dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet\n        dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet\n        dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet\n        dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet\n        dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet\n        dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet\n        dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet\n        dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet\n        dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet\n        dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet\n        dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet\n        dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet\n        dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet\n        dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet\n\n        return dst\n\n    set: (\n        a00, a10, a20, a30,\n        a01, a11, a21, a31,\n        a02, a12, a22, a32,\n        a03, a13, a23, a33,\n    ) ->\n        d = @data\n        d[0]=a00; d[4]=a10; d[8]=a20; d[12]=a30\n        d[1]=a01; d[5]=a11; d[9]=a21; d[13]=a31\n        d[2]=a02; d[6]=a12; d[10]=a22; d[14]=a32\n        d[3]=a03; d[7]=a13; d[11]=a23; d[15]=a33\n\n        return @\n"
  },
  {
    "path": "extra/matrix.js",
    "content": "// Generated by CoffeeScript 1.3.3\n(function() {\n  var Mat3, Mat4, arc, deg, pi, tau;\n\n  pi = Math.PI;\n\n  tau = 2 * pi;\n\n  deg = 360 / tau;\n\n  arc = tau / 360;\n\n  window.Mat3 = Mat3 = (function() {\n\n    function Mat3(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(9);\n      }\n      this.identity();\n    }\n\n    Mat3.prototype.identity = function() {\n      var d;\n      d = this.data;\n      d[0] = 1;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 1;\n      d[5] = 0;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 1;\n      return this;\n    };\n\n    Mat3.prototype.transpose = function() {\n      var a01, a02, a12, d;\n      d = this.data;\n      a01 = d[1];\n      a02 = d[2];\n      a12 = d[5];\n      d[1] = d[3];\n      d[2] = d[6];\n      d[3] = a01;\n      d[5] = d[7];\n      d[6] = a02;\n      d[7] = a12;\n      return this;\n    };\n\n    Mat3.prototype.mulVec3 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      this.mulVal3(vec.x, vec.y, vec.z, dst);\n      return dst;\n    };\n\n    Mat3.prototype.mulVal3 = function(x, y, z, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[3] * y + d[6] * z;\n      dst[1] = d[1] * x + d[4] * y + d[7] * z;\n      dst[2] = d[2] * x + d[5] * y + d[8] * z;\n      return this;\n    };\n\n    Mat3.prototype.rotatex = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(1, 0, 0, 0, c, s, 0, -s, c);\n    };\n\n    Mat3.prototype.rotatey = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(c, 0, -s, 0, 1, 0, s, 0, c);\n    };\n\n    Mat3.prototype.rotatez = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(c, s, 0, -s, c, 0, 0, 0, 1);\n    };\n\n    Mat3.prototype.amul = function(b00, b10, b20, b01, b11, b21, b02, b12, b22, b03, b13, b23) {\n      var a, a00, a01, a02, a10, a11, a12, a20, a21, a22;\n      a = this.data;\n      a00 = a[0];\n      a10 = a[1];\n      a20 = a[2];\n      a01 = a[3];\n      a11 = a[4];\n      a21 = a[5];\n      a02 = a[6];\n      a12 = a[7];\n      a22 = a[8];\n      a[0] = a00 * b00 + a01 * b10 + a02 * b20;\n      a[1] = a10 * b00 + a11 * b10 + a12 * b20;\n      a[2] = a20 * b00 + a21 * b10 + a22 * b20;\n      a[3] = a00 * b01 + a01 * b11 + a02 * b21;\n      a[4] = a10 * b01 + a11 * b11 + a12 * b21;\n      a[5] = a20 * b01 + a21 * b11 + a22 * b21;\n      a[6] = a00 * b02 + a01 * b12 + a02 * b22;\n      a[7] = a10 * b02 + a11 * b12 + a12 * b22;\n      a[8] = a20 * b02 + a21 * b12 + a22 * b22;\n      return this;\n    };\n\n    Mat3.prototype.log = function() {\n      var d;\n      d = this.data;\n      return console.log('%f, %f, %f,\\n%f, %f, %f, \\n%f, %f, %f, ', d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]);\n    };\n\n    return Mat3;\n\n  })();\n\n  window.Mat4 = Mat4 = (function() {\n\n    function Mat4(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(16);\n      }\n      this.identity();\n    }\n\n    Mat4.prototype.identity = function() {\n      var d;\n      d = this.data;\n      d[0] = 1;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 0;\n      d[5] = 1;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 0;\n      d[9] = 0;\n      d[10] = 1;\n      d[11] = 0;\n      d[12] = 0;\n      d[13] = 0;\n      d[14] = 0;\n      d[15] = 1;\n      return this;\n    };\n\n    Mat4.prototype.zero = function() {\n      var d;\n      d = this.data;\n      d[0] = 0;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 0;\n      d[5] = 0;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 0;\n      d[9] = 0;\n      d[10] = 0;\n      d[11] = 0;\n      d[12] = 0;\n      d[13] = 0;\n      d[14] = 0;\n      d[15] = 0;\n      return this;\n    };\n\n    Mat4.prototype.copy = function(dest) {\n      var dst, src;\n      src = this.data;\n      dst = dest.data;\n      dst[0] = src[0];\n      dst[1] = src[1];\n      dst[2] = src[2];\n      dst[3] = src[3];\n      dst[4] = src[4];\n      dst[5] = src[5];\n      dst[6] = src[6];\n      dst[7] = src[7];\n      dst[8] = src[8];\n      dst[9] = src[9];\n      dst[10] = src[10];\n      dst[11] = src[11];\n      dst[12] = src[12];\n      dst[13] = src[13];\n      dst[14] = src[14];\n      dst[15] = src[15];\n      return dest;\n    };\n\n    Mat4.prototype.toMat3 = function(dest) {\n      var dst, src;\n      src = this.data;\n      dst = dest.data;\n      dst[0] = src[0];\n      dst[1] = src[1];\n      dst[2] = src[2];\n      dst[3] = src[4];\n      dst[4] = src[5];\n      dst[5] = src[6];\n      dst[6] = src[8];\n      dst[7] = src[9];\n      dst[8] = src[10];\n      return dest;\n    };\n\n    Mat4.prototype.toMat3Rot = function(dest) {\n      var a00, a01, a02, a10, a11, a12, a20, a21, a22, b01, b11, b21, d, dst, id, src;\n      dst = dest.data;\n      src = this.data;\n      a00 = src[0];\n      a01 = src[1];\n      a02 = src[2];\n      a10 = src[4];\n      a11 = src[5];\n      a12 = src[6];\n      a20 = src[8];\n      a21 = src[9];\n      a22 = src[10];\n      b01 = a22 * a11 - a12 * a21;\n      b11 = -a22 * a10 + a12 * a20;\n      b21 = a21 * a10 - a11 * a20;\n      d = a00 * b01 + a01 * b11 + a02 * b21;\n      id = 1 / d;\n      dst[0] = b01 * id;\n      dst[3] = (-a22 * a01 + a02 * a21) * id;\n      dst[6] = (a12 * a01 - a02 * a11) * id;\n      dst[1] = b11 * id;\n      dst[4] = (a22 * a00 - a02 * a20) * id;\n      dst[7] = (-a12 * a00 + a02 * a10) * id;\n      dst[2] = b21 * id;\n      dst[5] = (-a21 * a00 + a01 * a20) * id;\n      dst[8] = (a11 * a00 - a01 * a10) * id;\n      return dest;\n    };\n\n    Mat4.prototype.perspective = function(fov, aspect, near, far) {\n      var bottom, d, left, right, top;\n      this.zero();\n      d = this.data;\n      top = near * Math.tan(fov * Math.PI / 360);\n      right = top * aspect;\n      left = -right;\n      bottom = -top;\n      d[0] = (2 * near) / (right - left);\n      d[5] = (2 * near) / (top - bottom);\n      d[8] = (right + left) / (right - left);\n      d[9] = (top + bottom) / (top - bottom);\n      d[10] = -(far + near) / (far - near);\n      d[11] = -1;\n      d[14] = -(2 * far * near) / (far - near);\n      return this;\n    };\n\n    Mat4.prototype.inversePerspective = function(fov, aspect, near, far) {\n      var bottom, dst, left, right, top;\n      this.zero();\n      dst = this.data;\n      top = near * Math.tan(fov * Math.PI / 360);\n      right = top * aspect;\n      left = -right;\n      bottom = -top;\n      dst[0] = (right - left) / (2 * near);\n      dst[5] = (top - bottom) / (2 * near);\n      dst[11] = -(far - near) / (2 * far * near);\n      dst[12] = (right + left) / (2 * near);\n      dst[13] = (top + bottom) / (2 * near);\n      dst[14] = -1;\n      dst[15] = (far + near) / (2 * far * near);\n      return this;\n    };\n\n    Mat4.prototype.ortho = function(near, far, top, bottom, left, right) {\n      var fn, rl, tb;\n      if (near == null) {\n        near = -1;\n      }\n      if (far == null) {\n        far = 1;\n      }\n      if (top == null) {\n        top = -1;\n      }\n      if (bottom == null) {\n        bottom = 1;\n      }\n      if (left == null) {\n        left = -1;\n      }\n      if (right == null) {\n        right = 1;\n      }\n      rl = right - left;\n      tb = top - bottom;\n      fn = far - near;\n      return this.set(2 / rl, 0, 0, -(left + right) / rl, 0, 2 / tb, 0, -(top + bottom) / tb, 0, 0, -2 / fn, -(far + near) / fn, 0, 0, 0, 1);\n    };\n\n    Mat4.prototype.inverseOrtho = function(near, far, top, bottom, left, right) {\n      var a, b, c, d, e, f, g;\n      if (near == null) {\n        near = -1;\n      }\n      if (far == null) {\n        far = 1;\n      }\n      if (top == null) {\n        top = -1;\n      }\n      if (bottom == null) {\n        bottom = 1;\n      }\n      if (left == null) {\n        left = -1;\n      }\n      if (right == null) {\n        right = 1;\n      }\n      a = (right - left) / 2;\n      b = (right + left) / 2;\n      c = (top - bottom) / 2;\n      d = (top + bottom) / 2;\n      e = (far - near) / -2;\n      f = (near + far) / 2;\n      g = 1;\n      return this.set(a, 0, 0, b, 0, c, 0, d, 0, 0, e, f, 0, 0, 0, g);\n    };\n\n    Mat4.prototype.fromRotationTranslation = function(quat, vec) {\n      var dest, w, wx, wy, wz, x, x2, xx, xy, xz, y, y2, yy, yz, z, z2, zz;\n      x = quat.x;\n      y = quat.y;\n      z = quat.z;\n      w = quat.w;\n      x2 = x + x;\n      y2 = y + y;\n      z2 = z + z;\n      xx = x * x2;\n      xy = x * y2;\n      xz = x * z2;\n      yy = y * y2;\n      yz = y * z2;\n      zz = z * z2;\n      wx = w * x2;\n      wy = w * y2;\n      wz = w * z2;\n      dest = this.data;\n      ' \\ndest[0] = 1 - 2.0 * y * y - 2.0 * y * y\\ndest[1] = 2 * x * y - 2.0 * w * z\\ndest[3] = 2 * x * z + 2.0 * w * y\\n\\ndest[4] = 2 * x * y + 2.0 * w * z\\ndest[5] = 1 - 2.0 * x * x - 2.0 * z * z\\ndest[6] = 2 * y * z - 2.0 * w * x\\n\\ndest[8] = 2 * x * z - 2.0 * w * y\\ndest[9] = 2 * y * z + 2.0 * w * x\\ndest[10] = 1 - 2.0 * x * x - 2.0 * y * y';\n\n      'dest[0] = 1 - 2.0 * y * y - 2.0 * y * y\\ndest[1] = 2 * x * y + 2.0 * w * z\\ndest[2] = 2 * x * z - 2.0 * w * y\\n\\ndest[4] = 2 * x * y - 2.0 * w * z\\ndest[5] = 1 - 2.0 * x * x - 2.0 * z * z\\ndest[6] = 2 * y * z + 2.0 * w * x\\n\\ndest[8] = 2 * x * z + 2.0 * w * y\\ndest[9] = 2 * y * z - 2.0 * w * x\\ndest[10] = 1 - 2.0 * x * x - 2.0 * y * y';\n\n      dest[0] = 1 - (yy + zz);\n      dest[1] = xy + wz;\n      dest[2] = xz - wy;\n      dest[3] = 0;\n      dest[4] = xy - wz;\n      dest[5] = 1 - (xx + zz);\n      dest[6] = yz + wx;\n      dest[7] = 0;\n      dest[8] = xz + wy;\n      dest[9] = yz - wx;\n      dest[10] = 1 - (xx + yy);\n      dest[11] = 0;\n      dest[12] = vec.x;\n      dest[13] = vec.y;\n      dest[14] = vec.z;\n      dest[15] = 1;\n      return this;\n    };\n\n    Mat4.prototype.translateVec3 = function(vec) {\n      return this.translateVal3(vec.x, vec.y, vec.z);\n    };\n\n    Mat4.prototype.translateVal3 = function(x, y, z) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, d;\n      d = this.data;\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[12] = a00 * x + a10 * y + a20 * z + d[12];\n      d[13] = a01 * x + a11 * y + a21 * z + d[13];\n      d[14] = a02 * x + a12 * y + a22 * z + d[14];\n      d[15] = a03 * x + a13 * y + a23 * z + d[15];\n      return this;\n    };\n\n    Mat4.prototype.rotatex = function(angle) {\n      var a10, a11, a12, a13, a20, a21, a22, a23, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[4] = a10 * c + a20 * s;\n      d[5] = a11 * c + a21 * s;\n      d[6] = a12 * c + a22 * s;\n      d[7] = a13 * c + a23 * s;\n      d[8] = a10 * -s + a20 * c;\n      d[9] = a11 * -s + a21 * c;\n      d[10] = a12 * -s + a22 * c;\n      d[11] = a13 * -s + a23 * c;\n      return this;\n    };\n\n    Mat4.prototype.rotatey = function(angle) {\n      var a00, a01, a02, a03, a20, a21, a22, a23, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[0] = a00 * c + a20 * -s;\n      d[1] = a01 * c + a21 * -s;\n      d[2] = a02 * c + a22 * -s;\n      d[3] = a03 * c + a23 * -s;\n      d[8] = a00 * s + a20 * c;\n      d[9] = a01 * s + a21 * c;\n      d[10] = a02 * s + a22 * c;\n      d[11] = a03 * s + a23 * c;\n      return this;\n    };\n\n    Mat4.prototype.rotatez = function(angle) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      d[0] = a00 * c + a10 * s;\n      d[1] = a01 * c + a11 * s;\n      d[2] = a02 * c + a12 * s;\n      d[3] = a03 * c + a13 * s;\n      d[4] = a00 * -s + a10 * c;\n      d[5] = a01 * -s + a11 * c;\n      d[6] = a02 * -s + a12 * c;\n      d[7] = a03 * -s + a13 * c;\n      return this;\n    };\n\n    Mat4.prototype.scale = function(scalar) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, d;\n      d = this.data;\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[0] = a00 * scalar;\n      d[1] = a01 * scalar;\n      d[2] = a02 * scalar;\n      d[3] = a03 * scalar;\n      d[4] = a10 * scalar;\n      d[5] = a11 * scalar;\n      d[6] = a12 * scalar;\n      d[7] = a13 * scalar;\n      d[8] = a20 * scalar;\n      d[9] = a21 * scalar;\n      d[10] = a22 * scalar;\n      d[11] = a23 * scalar;\n      return this;\n    };\n\n    Mat4.prototype.mulMat4 = function(other, dst) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, a30, a31, a32, a33, b0, b1, b2, b3, dest, mat, mat2;\n      if (dst == null) {\n        dst = this;\n      }\n      dest = dst.data;\n      mat = this.data;\n      mat2 = other.data;\n      a00 = mat[0];\n      a01 = mat[1];\n      a02 = mat[2];\n      a03 = mat[3];\n      a10 = mat[4];\n      a11 = mat[5];\n      a12 = mat[6];\n      a13 = mat[7];\n      a20 = mat[8];\n      a21 = mat[9];\n      a22 = mat[10];\n      a23 = mat[11];\n      a30 = mat[12];\n      a31 = mat[13];\n      a32 = mat[14];\n      a33 = mat[15];\n      b0 = mat2[0];\n      b1 = mat2[1];\n      b2 = mat2[2];\n      b3 = mat2[3];\n      dest[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[4];\n      b1 = mat2[5];\n      b2 = mat2[6];\n      b3 = mat2[7];\n      dest[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[8];\n      b1 = mat2[9];\n      b2 = mat2[10];\n      b3 = mat2[11];\n      dest[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[12];\n      b1 = mat2[13];\n      b2 = mat2[14];\n      b3 = mat2[15];\n      dest[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      return dst;\n    };\n\n    Mat4.prototype.mulVec3 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      return this.mulVal3(vec.x, vec.y, vec.z, dst);\n    };\n\n    Mat4.prototype.mulVal3 = function(x, y, z, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[4] * y + d[8] * z;\n      dst[1] = d[1] * x + d[5] * y + d[9] * z;\n      dst[2] = d[2] * x + d[6] * y + d[10] * z;\n      return dst;\n    };\n\n    Mat4.prototype.mulVec4 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      return this.mulVal4(vec.x, vec.y, vec.z, vec.w, dst);\n    };\n\n    Mat4.prototype.mulVal4 = function(x, y, z, w, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[4] * y + d[8] * z + d[12] * w;\n      dst[1] = d[1] * x + d[5] * y + d[9] * z + d[13] * w;\n      dst[2] = d[2] * x + d[6] * y + d[10] * z + d[14] * w;\n      dst[3] = d[3] * x + d[7] * y + d[11] * z + d[15] * w;\n      return dst;\n    };\n\n    Mat4.prototype.invert = function(dst) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, a30, a31, a32, a33, b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, d, dest, invDet, mat;\n      if (dst == null) {\n        dst = this;\n      }\n      mat = this.data;\n      dest = dst.data;\n      a00 = mat[0];\n      a01 = mat[1];\n      a02 = mat[2];\n      a03 = mat[3];\n      a10 = mat[4];\n      a11 = mat[5];\n      a12 = mat[6];\n      a13 = mat[7];\n      a20 = mat[8];\n      a21 = mat[9];\n      a22 = mat[10];\n      a23 = mat[11];\n      a30 = mat[12];\n      a31 = mat[13];\n      a32 = mat[14];\n      a33 = mat[15];\n      b00 = a00 * a11 - a01 * a10;\n      b01 = a00 * a12 - a02 * a10;\n      b02 = a00 * a13 - a03 * a10;\n      b03 = a01 * a12 - a02 * a11;\n      b04 = a01 * a13 - a03 * a11;\n      b05 = a02 * a13 - a03 * a12;\n      b06 = a20 * a31 - a21 * a30;\n      b07 = a20 * a32 - a22 * a30;\n      b08 = a20 * a33 - a23 * a30;\n      b09 = a21 * a32 - a22 * a31;\n      b10 = a21 * a33 - a23 * a31;\n      b11 = a22 * a33 - a23 * a32;\n      d = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n      if (d === 0) {\n        return;\n      }\n      invDet = 1 / d;\n      dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;\n      dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;\n      dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;\n      dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;\n      dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;\n      dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;\n      dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;\n      dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;\n      dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;\n      dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;\n      dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;\n      dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;\n      dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;\n      dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;\n      dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;\n      dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;\n      return dst;\n    };\n\n    Mat4.prototype.set = function(a00, a10, a20, a30, a01, a11, a21, a31, a02, a12, a22, a32, a03, a13, a23, a33) {\n      var d;\n      d = this.data;\n      d[0] = a00;\n      d[4] = a10;\n      d[8] = a20;\n      d[12] = a30;\n      d[1] = a01;\n      d[5] = a11;\n      d[9] = a21;\n      d[13] = a31;\n      d[2] = a02;\n      d[6] = a12;\n      d[10] = a22;\n      d[14] = a32;\n      d[3] = a03;\n      d[7] = a13;\n      d[11] = a23;\n      d[15] = a33;\n      return this;\n    };\n\n    return Mat4;\n\n  })();\n\n}).call(this);\n"
  },
  {
    "path": "extra/shims.coffee",
    "content": "if window.performance\n    if window.performance.now\n        now = -> window.performance.now()\n    else if window.performance.webkitNow\n        now = -> window.performance.webkitNow()\n    else if window.performance.mozNow\n        now = -> window.performance.mozNow()\n    else if window.performance.oNow\n        now = -> window.performance.oNow()\n    else\n        now = -> Date.now()\nelse\n    now = -> Date.now()\n\nstart = now()\nwindow.gettime = -> (now() - start)/1000\n\nif not window.requestAnimationFrame\n    if window.webkitRequestAnimationFrame\n        window.requestAnimationFrame = window.webkitRequestAnimationFrame\n    else if window.mozRequestAnimationFrame\n        window.requestAnimationFrame = window.mozRequestAnimationFrame\n    else if window.oRequestAnimationFrame\n        window.requestAnimationFrame = window.oRequestAnimationFrame\n    else\n        window.requestAnimationFrame = (fun) ->\n            setTimeout(fun, 1000/30)\n\nwindow.URL = window.URL or window.mozURL or window.webkitURL or window.oURL\nwindow.BlobBuilder = window.BlobBuilder or window.MozBlobBuilder or window.WebKitBlobBuilder or window.OBlobBuilder\n\nlog_count = 0\nwindow.console.logN = (n) ->\n    if log_count < n\n        log_count += 1\n        args = [].slice.call(arguments, 1)\n        console.log.apply console, args\n"
  },
  {
    "path": "extra/shims.js",
    "content": "// Generated by CoffeeScript 1.3.3\n(function() {\n  var log_count, now, start;\n\n  if (window.performance) {\n    if (window.performance.now) {\n      now = function() {\n        return window.performance.now();\n      };\n    } else if (window.performance.webkitNow) {\n      now = function() {\n        return window.performance.webkitNow();\n      };\n    } else if (window.performance.mozNow) {\n      now = function() {\n        return window.performance.mozNow();\n      };\n    } else if (window.performance.oNow) {\n      now = function() {\n        return window.performance.oNow();\n      };\n    } else {\n      now = function() {\n        return Date.now();\n      };\n    }\n  } else {\n    now = function() {\n      return Date.now();\n    };\n  }\n\n  start = now();\n\n  window.gettime = function() {\n    return (now() - start) / 1000;\n  };\n\n  if (!window.requestAnimationFrame) {\n    if (window.webkitRequestAnimationFrame) {\n      window.requestAnimationFrame = window.webkitRequestAnimationFrame;\n    } else if (window.mozRequestAnimationFrame) {\n      window.requestAnimationFrame = window.mozRequestAnimationFrame;\n    } else if (window.oRequestAnimationFrame) {\n      window.requestAnimationFrame = window.oRequestAnimationFrame;\n    } else {\n      window.requestAnimationFrame = function(fun) {\n        return setTimeout(fun, 1000 / 30);\n      };\n    }\n  }\n\n  window.URL = window.URL || window.mozURL || window.webkitURL || window.oURL;\n\n  window.BlobBuilder = window.BlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder || window.OBlobBuilder;\n\n  log_count = 0;\n\n  window.console.logN = function(n) {\n    var args;\n    if (log_count < n) {\n      log_count += 1;\n      args = [].slice.call(arguments, 1);\n      return console.log.apply(console, args);\n    }\n  };\n\n}).call(this);\n"
  },
  {
    "path": "extra/vector.coffee",
    "content": "window.Vec3 = class Vec3\n    @property 'x'\n        get: -> @data[0]\n        set: (val) -> @data[0] = val\n    @property 'y'\n        get: -> @data[1]\n        set: (val) -> @data[1] = val\n    @property 'z'\n        get: -> @data[2]\n        set: (val) -> @data[2] = val\n\n    @property 'length'\n        get: -> Math.sqrt(@x*@x + @y*@y + @z*@z)\n\n    constructor: (@data) ->\n        @data ?= new Float32Array 3\n\n    sub: (other, dst=@) ->\n        dst.x = @x - other.x\n        dst.y = @y - other.y\n        dst.z = @z - other.z\n        return dst\n\n    add: (other, dst=@) ->\n        dst.x = @x + other.x\n        dst.y = @y + other.y\n        dst.z = @z + other.z\n        return dst\n\n    addVal3: (x, y, z, dst=@) ->\n        dst.x = @x + x\n        dst.y = @y + y\n        dst.z = @z + z\n        return dst\n\n    mul: (scalar, dst=@) ->\n        dst.x = @x * scalar\n        dst.y = @y * scalar\n        dst.z = @z * scalar\n        return dst\n    \n    div: (scalar, dst=@) ->\n        dst.x = @x / scalar\n        dst.y = @y / scalar\n        dst.z = @z / scalar\n        return dst\n\n    divVal3: (x, y, z, dst=@) ->\n        dst.x = @x/x\n        dst.y = @y/y\n        dst.z = @z/z\n        return dst\n    \n    dot: (other) ->\n        return @x*other.x + @y*other.y + @z*other.z\n\n    normalize: (dst=@) ->\n        l = @length\n        if l > 0 then @mul 1/@length, dst\n        return dst\n\n    set: (x,y,z) ->\n        @x = x\n        @y = y\n        @z = z\n        return @\n\nwindow.Vec4 = class Vec4\n    @property 'x'\n        get: -> @data[0]\n        set: (val) -> @data[0] = val\n    @property 'y'\n        get: -> @data[1]\n        set: (val) -> @data[1] = val\n    @property 'z'\n        get: -> @data[2]\n        set: (val) -> @data[2] = val\n    @property 'w'\n        get: -> @data[3]\n        set: (val) -> @data[3] = val\n\n    constructor: (@data) ->\n        @data ?= new Float32Array 4\n\n    sub: (other, dst=@) ->\n        dst.x = @x - other.x\n        dst.y = @y - other.y\n        dst.z = @z - other.z\n        dst.w = @w - other.w\n\n        return dst\n\n    dot: (other) ->\n        return @x*other.x + @y*other.y + @z*other.z + @w*other.w\n\n    toVec3: (dst) ->\n        dst ?= new Vec3()\n        dst.x = @x\n        dst.y = @y\n        dst.z = @z\n\n        return dst\n"
  },
  {
    "path": "extra/vector.js",
    "content": "// Generated by CoffeeScript 1.3.3\n(function() {\n  var Vec3, Vec4;\n\n  window.Vec3 = Vec3 = (function() {\n\n    Vec3.property('x', {\n      get: function() {\n        return this.data[0];\n      },\n      set: function(val) {\n        return this.data[0] = val;\n      }\n    });\n\n    Vec3.property('y', {\n      get: function() {\n        return this.data[1];\n      },\n      set: function(val) {\n        return this.data[1] = val;\n      }\n    });\n\n    Vec3.property('z', {\n      get: function() {\n        return this.data[2];\n      },\n      set: function(val) {\n        return this.data[2] = val;\n      }\n    });\n\n    Vec3.property('length', {\n      get: function() {\n        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n      }\n    });\n\n    function Vec3(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(3);\n      }\n    }\n\n    Vec3.prototype.sub = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x - other.x;\n      dst.y = this.y - other.y;\n      dst.z = this.z - other.z;\n      return dst;\n    };\n\n    Vec3.prototype.add = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x + other.x;\n      dst.y = this.y + other.y;\n      dst.z = this.z + other.z;\n      return dst;\n    };\n\n    Vec3.prototype.addVal3 = function(x, y, z, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x + x;\n      dst.y = this.y + y;\n      dst.z = this.z + z;\n      return dst;\n    };\n\n    Vec3.prototype.mul = function(scalar, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x * scalar;\n      dst.y = this.y * scalar;\n      dst.z = this.z * scalar;\n      return dst;\n    };\n\n    Vec3.prototype.div = function(scalar, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x / scalar;\n      dst.y = this.y / scalar;\n      dst.z = this.z / scalar;\n      return dst;\n    };\n\n    Vec3.prototype.divVal3 = function(x, y, z, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x / x;\n      dst.y = this.y / y;\n      dst.z = this.z / z;\n      return dst;\n    };\n\n    Vec3.prototype.dot = function(other) {\n      return this.x * other.x + this.y * other.y + this.z * other.z;\n    };\n\n    Vec3.prototype.normalize = function(dst) {\n      var l;\n      if (dst == null) {\n        dst = this;\n      }\n      l = this.length;\n      if (l > 0) {\n        this.mul(1 / this.length, dst);\n      }\n      return dst;\n    };\n\n    Vec3.prototype.set = function(x, y, z) {\n      this.x = x;\n      this.y = y;\n      this.z = z;\n      return this;\n    };\n\n    return Vec3;\n\n  })();\n\n  window.Vec4 = Vec4 = (function() {\n\n    Vec4.property('x', {\n      get: function() {\n        return this.data[0];\n      },\n      set: function(val) {\n        return this.data[0] = val;\n      }\n    });\n\n    Vec4.property('y', {\n      get: function() {\n        return this.data[1];\n      },\n      set: function(val) {\n        return this.data[1] = val;\n      }\n    });\n\n    Vec4.property('z', {\n      get: function() {\n        return this.data[2];\n      },\n      set: function(val) {\n        return this.data[2] = val;\n      }\n    });\n\n    Vec4.property('w', {\n      get: function() {\n        return this.data[3];\n      },\n      set: function(val) {\n        return this.data[3] = val;\n      }\n    });\n\n    function Vec4(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(4);\n      }\n    }\n\n    Vec4.prototype.sub = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x - other.x;\n      dst.y = this.y - other.y;\n      dst.z = this.z - other.z;\n      dst.w = this.w - other.w;\n      return dst;\n    };\n\n    Vec4.prototype.dot = function(other) {\n      return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;\n    };\n\n    Vec4.prototype.toVec3 = function(dst) {\n      if (dst == null) {\n        dst = new Vec3();\n      }\n      dst.x = this.x;\n      dst.y = this.y;\n      dst.z = this.z;\n      return dst;\n    };\n\n    return Vec4;\n\n  })();\n\n}).call(this);\n"
  },
  {
    "path": "lib/audio.coffee",
    "content": "class Backend\n    constructor: ->\n        @loading = 0\n        @handlers = []\n    \n    loaded: ->\n        if @loading == 0\n            for handler in @handlers\n                if handler.event == 'loaded' then handler.callback.apply(handler)\n        return\n\n    bind: (event, callback) ->\n        handler =\n            event: event\n            callback: callback\n        @handlers.push handler\n        return handler\n\n    unbind: (handler) ->\n        index = @handlers.indexOf handler\n        if index >= 0 then @handlers.splice index, 1\n\nclass HTMLAudio extends Backend\n    @available = (\n        (window.Audio != undefined) and\n        (window.URL != undefined) and\n        (window.BlobBuilder != undefined)\n    )\n\n    class Sample\n        constructor: (@backend, data) ->\n            @backend.loading += 1\n            @url = blob.pack data, 'audio/ogg'\n        \n        play: (looping) ->\n            voice = @backend.getFree()\n            voice.play(@url, looping) if voice\n\n    class Voice\n        constructor: (backend, @id) ->\n            self = @\n            @audio = new Audio()\n            @audio.onended = ->\n                backend.ended(self)\n\n        play: (url) ->\n            @audio.src = url\n            @audio.play()\n\n    constructor: ->\n        @free = {}\n        @playing = {}\n\n        for id in [0...20]\n            @free[id] = new Voice(@, id)\n\n        setInterval @check, 100\n\n    check: =>\n        #for id, voice of @playing\n            #console.log voice.audio.duration\n\n    getFree: ->\n        for id, voice of @free\n            delete @free[id]\n            @playing[id] = voice\n            return voice\n\n    ended: (voice) ->\n        @free[voice.id] = voice\n        delete @playing[voice.id]\n    \n    createSample: (data) ->\n        @start_time = gettime()\n        return new Sample @, data\n\nclass WebAudio extends Backend\n    @available = window.webkitAudioContext != undefined\n    \n    constructor: ->\n        super()\n        @ctx = new webkitAudioContext()\n\n    play: (buffer, looping=false) ->\n        source = @ctx.createBufferSource()\n        source.buffer = buffer\n        source.loop = looping\n        source.connect(@ctx.destination)\n        source.noteOn(@ctx.currentTime)\n   \n    decode: (data, callback) ->\n        @ctx.decodeAudioData data, (buffer) ->\n            callback(buffer)\n\nif WebAudio.available\n    backend = new WebAudio()\n\n    exports.decode = (data, callback) ->\n        backend.decode data, callback\n\n    exports.play = (buffer) ->\n        backend.play buffer\nelse\n    exports.decode = (data, callback) ->\n    exports.play = (buffer) ->\n"
  },
  {
    "path": "lib/audio.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Backend, HTMLAudio, WebAudio, backend,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nBackend = (function() {\n\n  function Backend() {\n    this.loading = 0;\n    this.handlers = [];\n  }\n\n  Backend.prototype.loaded = function() {\n    var handler, _i, _len, _ref;\n    if (this.loading === 0) {\n      _ref = this.handlers;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        handler = _ref[_i];\n        if (handler.event === 'loaded') {\n          handler.callback.apply(handler);\n        }\n      }\n    }\n  };\n\n  Backend.prototype.bind = function(event, callback) {\n    var handler;\n    handler = {\n      event: event,\n      callback: callback\n    };\n    this.handlers.push(handler);\n    return handler;\n  };\n\n  Backend.prototype.unbind = function(handler) {\n    var index;\n    index = this.handlers.indexOf(handler);\n    if (index >= 0) {\n      return this.handlers.splice(index, 1);\n    }\n  };\n\n  return Backend;\n\n})();\n\nHTMLAudio = (function(_super) {\n  var Sample, Voice;\n\n  __extends(HTMLAudio, _super);\n\n  HTMLAudio.available = (window.Audio !== void 0) && (window.URL !== void 0) && (window.BlobBuilder !== void 0);\n\n  Sample = (function() {\n\n    function Sample(backend, data) {\n      this.backend = backend;\n      this.backend.loading += 1;\n      this.url = blob.pack(data, 'audio/ogg');\n    }\n\n    Sample.prototype.play = function(looping) {\n      var voice;\n      voice = this.backend.getFree();\n      if (voice) {\n        return voice.play(this.url, looping);\n      }\n    };\n\n    return Sample;\n\n  })();\n\n  Voice = (function() {\n\n    function Voice(backend, id) {\n      var self;\n      this.id = id;\n      self = this;\n      this.audio = new Audio();\n      this.audio.onended = function() {\n        return backend.ended(self);\n      };\n    }\n\n    Voice.prototype.play = function(url) {\n      this.audio.src = url;\n      return this.audio.play();\n    };\n\n    return Voice;\n\n  })();\n\n  function HTMLAudio() {\n    this.check = __bind(this.check, this);\n\n    var id, _i;\n    this.free = {};\n    this.playing = {};\n    for (id = _i = 0; _i < 20; id = ++_i) {\n      this.free[id] = new Voice(this, id);\n    }\n    setInterval(this.check, 100);\n  }\n\n  HTMLAudio.prototype.check = function() {};\n\n  HTMLAudio.prototype.getFree = function() {\n    var id, voice, _ref;\n    _ref = this.free;\n    for (id in _ref) {\n      voice = _ref[id];\n      delete this.free[id];\n      this.playing[id] = voice;\n      return voice;\n    }\n  };\n\n  HTMLAudio.prototype.ended = function(voice) {\n    this.free[voice.id] = voice;\n    return delete this.playing[voice.id];\n  };\n\n  HTMLAudio.prototype.createSample = function(data) {\n    this.start_time = gettime();\n    return new Sample(this, data);\n  };\n\n  return HTMLAudio;\n\n})(Backend);\n\nWebAudio = (function(_super) {\n\n  __extends(WebAudio, _super);\n\n  WebAudio.available = window.webkitAudioContext !== void 0;\n\n  function WebAudio() {\n    WebAudio.__super__.constructor.call(this);\n    this.ctx = new webkitAudioContext();\n  }\n\n  WebAudio.prototype.play = function(buffer, looping) {\n    var source;\n    if (looping == null) {\n      looping = false;\n    }\n    source = this.ctx.createBufferSource();\n    source.buffer = buffer;\n    source.loop = looping;\n    source.connect(this.ctx.destination);\n    return source.noteOn(this.ctx.currentTime);\n  };\n\n  WebAudio.prototype.decode = function(data, callback) {\n    return this.ctx.decodeAudioData(data, function(buffer) {\n      return callback(buffer);\n    });\n  };\n\n  return WebAudio;\n\n})(Backend);\n\nif (WebAudio.available) {\n  backend = new WebAudio();\n  exports.decode = function(data, callback) {\n    return backend.decode(data, callback);\n  };\n  exports.play = function(buffer) {\n    return backend.play(buffer);\n  };\n} else {\n  exports.decode = function(data, callback) {};\n  exports.play = function(buffer) {};\n}\n"
  },
  {
    "path": "lib/camera.coffee",
    "content": "keys = require 'keys'\n\nclass MouseDrag\n    constructor: (@which) ->\n        @x = 0\n        @y = 0\n\n        @lx = 0\n        @ly = 0\n        @pressed = false\n\n        if navigator.appVersion.indexOf('Mac') != -1\n            $('#ui').bind 'mousewheel', (event) =>\n                event.preventDefault()\n                event.stopImmediatePropagation()\n                event.stopPropagation()\n                \n                @x += event.originalEvent.wheelDeltaX*0.25\n                @y += event.originalEvent.wheelDeltaY*0.25\n                return false\n\n        $('#ui').mousedown (event) =>\n            if event.which == @which\n                @lx = event.pageX\n                @ly = event.pageY\n                @pressed = true\n            return undefined\n\n        $(document).mouseup =>\n            @pressed = false\n            return undefined\n\n        $(document).mousemove (event) =>\n            if @pressed and event.which == @which\n                x = event.pageX\n                y = event.pageY\n                @x += x - @lx\n                @y += y - @ly\n                @lx = x\n                @ly = y\n                return false\n            return undefined\n\n    reset: ->\n        @x = 0\n        @y = 0\n\nclass Camera\n    constructor: (@delta=1/180, @near=0.1, @far=1000) ->\n        @last_gui_update = gettime()\n        @time = gettime()\n        @proj = new Mat4()\n        @inv_proj = new Mat4()\n        @view = new Mat4()\n        @inv_view = new Mat4()\n        @rot = new Mat3()\n        @inv_rot = new Mat3()\n        @acc = new Vec3()\n\n    aspect: (width, height) ->\n        @proj.perspective 75, width/height, @near, @far\n        @inv_proj.inversePerspective 75, width/height, @near, @far\n    \n    step: ->\n        @accelerate()\n        @limit()\n        @move()\n        @limit()\n        @time += @delta\n    \n    update: ->\n        now = gettime()\n\n        if now - @last_gui_update > 0.5\n            @guiUpdate()\n            @last_gui_update = now\n\n        if now - @time > @delta*30\n            @time = now - @delta*30\n\n        while @time < now\n            @step()\n        @finish()\n\n        @view.invert @inv_view.identity()\n        @view.toMat3 @rot.identity()\n        @inv_view.toMat3 @inv_rot.identity()\n\n    limit: ->\n    guiUpdate: ->\n\nexports.GameCam = class GameCam extends Camera\n    constructor: ({@sl, @sr, delta, x, y, z}={}) ->\n        super(delta)\n        @realpos = new Vec4()\n        @sl ?= 200\n        @sr ?= 100\n        x ?= 0\n        y ?= 0\n        z ?= 0\n\n        @mouse = new MouseDrag(3)\n\n        @target_height = 0\n        @height = 0\n\n        @x=x; @lx=x\n        #@y=y; @ly=y\n        @z=z; @lz=z\n        @o=0; @lo=0\n        @d=0; @ld=0; @ad=0\n            \n        $(document).bind 'mousewheel', (event) =>\n            event.preventDefault()\n            event.stopImmediatePropagation()\n            event.stopPropagation()\n            \n            @ad -= event.originalEvent.wheelDeltaY\n            return false\n\n    accelerate: ->\n        sl = @delta*@delta*@sl\n        sr = @delta*@delta*@sr\n        \n        ctrl_x = if keys.a then -1 else if keys.d then 1 else 0\n        ctrl_y = if keys.q then -1 else if keys.e then 1 else 0\n        ctrl_z = if keys.w then -1 else if keys.s then 1 else 0\n\n        ax = ctrl_x * sl\n        #ay = ctrl_y * sl\n        az = ctrl_z * sl\n        \n        @rot\n            .identity()\n            .rotatey(-@o)\n            .mulVal3(ax, 0, az, @acc)\n\n        @x += @acc.x\n        #@y += @acc.y\n        @z += @acc.z\n        @o += @mouse.x * sr\n        @d += @ad * @delta * @delta * 20\n       \n        move = @delta*@delta*4000\n        if move > 1 then move = 1\n        @height = @height + (@target_height - @height) * move\n\n    move: ->\n        retl = 0.97\n        retr = 0.94\n        x = @x + (@x - @lx) * retl\n        #y = @y + (@y - @ly) * retl\n        z = @z + (@z - @lz) * retl\n        d = @d + (@d - @ld) * retl\n        o = @o + (@o - @lo) * retr\n\n        @lx = @x; @x = x\n        #@ly = @y; @y = y\n        @lz = @z; @z = z\n        @lo = @o; @o = o\n        @ld = @d; @d = d\n\n\n    limit: ->\n        if @d < 0 then @d = 0\n        else if @d > 30 then @d = 30\n\n        high = 128+64\n        low = 128-64\n        if @x < low then @x = low\n        else if @x > high then @x = high\n        \n        if @z < low then @z = low\n        else if @z > high then @z = high\n\n    finish: ->\n        @mouse.reset()\n        @ad = 0\n        @view\n            .identity()\n            .translateVal3(0, 0, -@d-5)\n            .rotatex(25+(@d/30)*40)\n            .rotatey(@o)\n            .translateVal3(-@x, -@height, -@z)\n\n    update: (picker) ->\n        @view\n            .identity()\n            .translateVal3(0, 0, -@d-5)\n            .rotatex(25+(@d/30)*40)\n            .rotatey(@o)\n            .translateVal3(-@x, 0, -@z)\n        @view.invert @inv_view.identity()\n\n        h1 = picker.getHeight @x, @z\n        @inv_view.mulVal4 0, 0, 0, 1, @realpos\n        h2 = picker.getHeight(@realpos.x, @realpos.z)+2\n        real_height = h1+@realpos.y\n        if real_height < h2\n            diff = h2 - real_height\n            @target_height = h1 + diff\n        else\n            @target_height = h1\n\n        super()\n\nexports.Orbit = class Orbit extends Camera\n    constructor: ({@sr, delta, x, y, z, @dist}={}) ->\n        super(delta)\n        @sr ?= 100\n        @dist ?= 0.6\n\n        @mouse = new MouseDrag(1)\n\n        @o=0; @lo=0\n        @p=0; @lp=0\n            \n    accelerate: ->\n        sr = @delta*@delta*@sr\n        @o += @mouse.x * sr\n        @p += @mouse.y * sr\n\n    move: ->\n        retr = 0.94\n        o = @o + (@o - @lo) * retr\n        p = @p + (@p - @lp) * retr\n\n        @lo = @o; @o = o\n        @lp = @p; @p = p\n\n    finish: ->\n        @mouse.reset()\n\n    update: () ->\n        @view\n            .identity()\n            .translateVal3(0, 0, -@dist)\n            .rotatex(@p)\n            .rotatey(@o)\n        @view.invert @inv_view.identity()\n\n        super()\n\nexports.FlyCam = class FlyCam extends Camera\n    constructor: ({@sl, @gui, @sr, delta, near, far, lookbutton, x, y, z, o, p}={}) ->\n        super(delta, near, far)\n        @sl ?= 50\n        @sr ?= 100\n        lookbutton ?= 1\n        x ?= 0\n        y ?= 0\n        z ?= 0\n        o ?= 0\n        p ?= 0\n\n        @mouse = new MouseDrag(lookbutton)\n\n        @x=x; @lx=x\n        @y=y; @ly=y\n        @z=z; @lz=z\n        @o=o; @lo=o\n        @p=p; @lp=p\n\n        folder = @gui.addFolder('Camera')\n        @gui.remember @\n        @xgui = folder.add(@, 'x', -30.0, 30.0).onChange(@guiChanged)\n        @ygui = folder.add(@, 'y', -30.0, 30.0).onChange(@guiChanged)\n        @zgui = folder.add(@, 'z', -30.0, 30.0).onChange(@guiChanged)\n        @go = @o\n        @ogui = folder.add(@, 'go', 0.0, 360.0).name('Orientation').onChange(@guiChanged)\n        @pgui = folder.add(@, 'p', -80.0, 80.0).name('Pitch').onChange(@guiChanged)\n        @guiChanged()\n\n    guiChanged: =>\n        @lx=@x\n        @ly=@y\n        @lz=@z\n        @o=@go; @lo=@go\n        @lp=@p\n\n    guiUpdate: ->\n        @go = @o % 360\n        @xgui.updateDisplay()\n        @ygui.updateDisplay()\n        @zgui.updateDisplay()\n        @ogui.updateDisplay()\n        @pgui.updateDisplay()\n\n    accelerate: ->\n        sl = @delta*@delta*@sl\n        sr = @delta*@delta*@sr\n        \n        ctrl_x = if keys.a then -1 else if keys.d then 1 else 0\n        ctrl_y = if keys.q then -1 else if keys.e then 1 else 0\n        ctrl_z = if keys.w then -1 else if keys.s then 1 else 0\n\n        ax = ctrl_x * sl\n        ay = ctrl_y * sl\n        az = ctrl_z * sl\n        \n        @rot\n            .identity()\n            .rotatey(-@o)\n            .rotatex(-@p)\n            .mulVal3(ax, ay, az, @acc)\n\n        @x += @acc.x\n        @y += @acc.y\n        @z += @acc.z\n        @o += @mouse.x * sr\n        @p += @mouse.y * sr\n\n    move: ->\n        retl = 0.97\n        retr = 0.94\n        x = @x + (@x - @lx) * retl\n        y = @y + (@y - @ly) * retl\n        z = @z + (@z - @lz) * retl\n        o = @o + (@o - @lo) * retr\n        p = @p + (@p - @lp) * retr\n\n        if p > 80 then p = 80\n        else if p < -80 then p = -80\n\n        @lx = @x; @x = x\n        @ly = @y; @y = y\n        @lz = @z; @z = z\n        @lo = @o; @o = o\n        @lp = @p; @p = p\n\n    finish: ->\n        @mouse.reset()\n        @view\n            .identity()\n            .rotatex(@p)\n            .rotatey(@o)\n            .translateVal3(-@x, -@y, -@z)\n"
  },
  {
    "path": "lib/camera.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Camera, FlyCam, GameCam, MouseDrag, Orbit, keys,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nkeys = require('keys');\n\nMouseDrag = (function() {\n\n  function MouseDrag(which) {\n    var _this = this;\n    this.which = which;\n    this.x = 0;\n    this.y = 0;\n    this.lx = 0;\n    this.ly = 0;\n    this.pressed = false;\n    if (navigator.appVersion.indexOf('Mac') !== -1) {\n      $('#ui').bind('mousewheel', function(event) {\n        event.preventDefault();\n        event.stopImmediatePropagation();\n        event.stopPropagation();\n        _this.x += event.originalEvent.wheelDeltaX * 0.25;\n        _this.y += event.originalEvent.wheelDeltaY * 0.25;\n        return false;\n      });\n    }\n    $('#ui').mousedown(function(event) {\n      if (event.which === _this.which) {\n        _this.lx = event.pageX;\n        _this.ly = event.pageY;\n        _this.pressed = true;\n      }\n      return void 0;\n    });\n    $(document).mouseup(function() {\n      _this.pressed = false;\n      return void 0;\n    });\n    $(document).mousemove(function(event) {\n      var x, y;\n      if (_this.pressed && event.which === _this.which) {\n        x = event.pageX;\n        y = event.pageY;\n        _this.x += x - _this.lx;\n        _this.y += y - _this.ly;\n        _this.lx = x;\n        _this.ly = y;\n        return false;\n      }\n      return void 0;\n    });\n  }\n\n  MouseDrag.prototype.reset = function() {\n    this.x = 0;\n    return this.y = 0;\n  };\n\n  return MouseDrag;\n\n})();\n\nCamera = (function() {\n\n  function Camera(delta, near, far) {\n    this.delta = delta != null ? delta : 1 / 180;\n    this.near = near != null ? near : 0.1;\n    this.far = far != null ? far : 1000;\n    this.last_gui_update = gettime();\n    this.time = gettime();\n    this.proj = new Mat4();\n    this.inv_proj = new Mat4();\n    this.view = new Mat4();\n    this.inv_view = new Mat4();\n    this.rot = new Mat3();\n    this.inv_rot = new Mat3();\n    this.acc = new Vec3();\n  }\n\n  Camera.prototype.aspect = function(width, height) {\n    this.proj.perspective(75, width / height, this.near, this.far);\n    return this.inv_proj.inversePerspective(75, width / height, this.near, this.far);\n  };\n\n  Camera.prototype.step = function() {\n    this.accelerate();\n    this.limit();\n    this.move();\n    this.limit();\n    return this.time += this.delta;\n  };\n\n  Camera.prototype.update = function() {\n    var now;\n    now = gettime();\n    if (now - this.last_gui_update > 0.5) {\n      this.guiUpdate();\n      this.last_gui_update = now;\n    }\n    if (now - this.time > this.delta * 30) {\n      this.time = now - this.delta * 30;\n    }\n    while (this.time < now) {\n      this.step();\n    }\n    this.finish();\n    this.view.invert(this.inv_view.identity());\n    this.view.toMat3(this.rot.identity());\n    return this.inv_view.toMat3(this.inv_rot.identity());\n  };\n\n  Camera.prototype.limit = function() {};\n\n  Camera.prototype.guiUpdate = function() {};\n\n  return Camera;\n\n})();\n\nexports.GameCam = GameCam = (function(_super) {\n\n  __extends(GameCam, _super);\n\n  function GameCam(_arg) {\n    var delta, x, y, z, _ref, _ref1, _ref2,\n      _this = this;\n    _ref = _arg != null ? _arg : {}, this.sl = _ref.sl, this.sr = _ref.sr, delta = _ref.delta, x = _ref.x, y = _ref.y, z = _ref.z;\n    GameCam.__super__.constructor.call(this, delta);\n    this.realpos = new Vec4();\n    if ((_ref1 = this.sl) == null) {\n      this.sl = 200;\n    }\n    if ((_ref2 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if (x == null) {\n      x = 0;\n    }\n    if (y == null) {\n      y = 0;\n    }\n    if (z == null) {\n      z = 0;\n    }\n    this.mouse = new MouseDrag(3);\n    this.target_height = 0;\n    this.height = 0;\n    this.x = x;\n    this.lx = x;\n    this.z = z;\n    this.lz = z;\n    this.o = 0;\n    this.lo = 0;\n    this.d = 0;\n    this.ld = 0;\n    this.ad = 0;\n    $(document).bind('mousewheel', function(event) {\n      event.preventDefault();\n      event.stopImmediatePropagation();\n      event.stopPropagation();\n      _this.ad -= event.originalEvent.wheelDeltaY;\n      return false;\n    });\n  }\n\n  GameCam.prototype.accelerate = function() {\n    var ax, az, ctrl_x, ctrl_y, ctrl_z, move, sl, sr;\n    sl = this.delta * this.delta * this.sl;\n    sr = this.delta * this.delta * this.sr;\n    ctrl_x = keys.a ? -1 : keys.d ? 1 : 0;\n    ctrl_y = keys.q ? -1 : keys.e ? 1 : 0;\n    ctrl_z = keys.w ? -1 : keys.s ? 1 : 0;\n    ax = ctrl_x * sl;\n    az = ctrl_z * sl;\n    this.rot.identity().rotatey(-this.o).mulVal3(ax, 0, az, this.acc);\n    this.x += this.acc.x;\n    this.z += this.acc.z;\n    this.o += this.mouse.x * sr;\n    this.d += this.ad * this.delta * this.delta * 20;\n    move = this.delta * this.delta * 4000;\n    if (move > 1) {\n      move = 1;\n    }\n    return this.height = this.height + (this.target_height - this.height) * move;\n  };\n\n  GameCam.prototype.move = function() {\n    var d, o, retl, retr, x, z;\n    retl = 0.97;\n    retr = 0.94;\n    x = this.x + (this.x - this.lx) * retl;\n    z = this.z + (this.z - this.lz) * retl;\n    d = this.d + (this.d - this.ld) * retl;\n    o = this.o + (this.o - this.lo) * retr;\n    this.lx = this.x;\n    this.x = x;\n    this.lz = this.z;\n    this.z = z;\n    this.lo = this.o;\n    this.o = o;\n    this.ld = this.d;\n    return this.d = d;\n  };\n\n  GameCam.prototype.limit = function() {\n    var high, low;\n    if (this.d < 0) {\n      this.d = 0;\n    } else if (this.d > 30) {\n      this.d = 30;\n    }\n    high = 128 + 64;\n    low = 128 - 64;\n    if (this.x < low) {\n      this.x = low;\n    } else if (this.x > high) {\n      this.x = high;\n    }\n    if (this.z < low) {\n      return this.z = low;\n    } else if (this.z > high) {\n      return this.z = high;\n    }\n  };\n\n  GameCam.prototype.finish = function() {\n    this.mouse.reset();\n    this.ad = 0;\n    return this.view.identity().translateVal3(0, 0, -this.d - 5).rotatex(25 + (this.d / 30) * 40).rotatey(this.o).translateVal3(-this.x, -this.height, -this.z);\n  };\n\n  GameCam.prototype.update = function(picker) {\n    var diff, h1, h2, real_height;\n    this.view.identity().translateVal3(0, 0, -this.d - 5).rotatex(25 + (this.d / 30) * 40).rotatey(this.o).translateVal3(-this.x, 0, -this.z);\n    this.view.invert(this.inv_view.identity());\n    h1 = picker.getHeight(this.x, this.z);\n    this.inv_view.mulVal4(0, 0, 0, 1, this.realpos);\n    h2 = picker.getHeight(this.realpos.x, this.realpos.z) + 2;\n    real_height = h1 + this.realpos.y;\n    if (real_height < h2) {\n      diff = h2 - real_height;\n      this.target_height = h1 + diff;\n    } else {\n      this.target_height = h1;\n    }\n    return GameCam.__super__.update.call(this);\n  };\n\n  return GameCam;\n\n})(Camera);\n\nexports.Orbit = Orbit = (function(_super) {\n\n  __extends(Orbit, _super);\n\n  function Orbit(_arg) {\n    var delta, x, y, z, _ref, _ref1, _ref2;\n    _ref = _arg != null ? _arg : {}, this.sr = _ref.sr, delta = _ref.delta, x = _ref.x, y = _ref.y, z = _ref.z, this.dist = _ref.dist;\n    Orbit.__super__.constructor.call(this, delta);\n    if ((_ref1 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if ((_ref2 = this.dist) == null) {\n      this.dist = 0.6;\n    }\n    this.mouse = new MouseDrag(1);\n    this.o = 0;\n    this.lo = 0;\n    this.p = 0;\n    this.lp = 0;\n  }\n\n  Orbit.prototype.accelerate = function() {\n    var sr;\n    sr = this.delta * this.delta * this.sr;\n    this.o += this.mouse.x * sr;\n    return this.p += this.mouse.y * sr;\n  };\n\n  Orbit.prototype.move = function() {\n    var o, p, retr;\n    retr = 0.94;\n    o = this.o + (this.o - this.lo) * retr;\n    p = this.p + (this.p - this.lp) * retr;\n    this.lo = this.o;\n    this.o = o;\n    this.lp = this.p;\n    return this.p = p;\n  };\n\n  Orbit.prototype.finish = function() {\n    return this.mouse.reset();\n  };\n\n  Orbit.prototype.update = function() {\n    this.view.identity().translateVal3(0, 0, -this.dist).rotatex(this.p).rotatey(this.o);\n    this.view.invert(this.inv_view.identity());\n    return Orbit.__super__.update.call(this);\n  };\n\n  return Orbit;\n\n})(Camera);\n\nexports.FlyCam = FlyCam = (function(_super) {\n\n  __extends(FlyCam, _super);\n\n  function FlyCam(_arg) {\n    var delta, far, folder, lookbutton, near, o, p, x, y, z, _ref, _ref1, _ref2;\n    _ref = _arg != null ? _arg : {}, this.sl = _ref.sl, this.gui = _ref.gui, this.sr = _ref.sr, delta = _ref.delta, near = _ref.near, far = _ref.far, lookbutton = _ref.lookbutton, x = _ref.x, y = _ref.y, z = _ref.z, o = _ref.o, p = _ref.p;\n    this.guiChanged = __bind(this.guiChanged, this);\n\n    FlyCam.__super__.constructor.call(this, delta, near, far);\n    if ((_ref1 = this.sl) == null) {\n      this.sl = 50;\n    }\n    if ((_ref2 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if (lookbutton == null) {\n      lookbutton = 1;\n    }\n    if (x == null) {\n      x = 0;\n    }\n    if (y == null) {\n      y = 0;\n    }\n    if (z == null) {\n      z = 0;\n    }\n    if (o == null) {\n      o = 0;\n    }\n    if (p == null) {\n      p = 0;\n    }\n    this.mouse = new MouseDrag(lookbutton);\n    this.x = x;\n    this.lx = x;\n    this.y = y;\n    this.ly = y;\n    this.z = z;\n    this.lz = z;\n    this.o = o;\n    this.lo = o;\n    this.p = p;\n    this.lp = p;\n    folder = this.gui.addFolder('Camera');\n    this.gui.remember(this);\n    this.xgui = folder.add(this, 'x', -30.0, 30.0).onChange(this.guiChanged);\n    this.ygui = folder.add(this, 'y', -30.0, 30.0).onChange(this.guiChanged);\n    this.zgui = folder.add(this, 'z', -30.0, 30.0).onChange(this.guiChanged);\n    this.go = this.o;\n    this.ogui = folder.add(this, 'go', 0.0, 360.0).name('Orientation').onChange(this.guiChanged);\n    this.pgui = folder.add(this, 'p', -80.0, 80.0).name('Pitch').onChange(this.guiChanged);\n    this.guiChanged();\n  }\n\n  FlyCam.prototype.guiChanged = function() {\n    this.lx = this.x;\n    this.ly = this.y;\n    this.lz = this.z;\n    this.o = this.go;\n    this.lo = this.go;\n    return this.lp = this.p;\n  };\n\n  FlyCam.prototype.guiUpdate = function() {\n    this.go = this.o % 360;\n    this.xgui.updateDisplay();\n    this.ygui.updateDisplay();\n    this.zgui.updateDisplay();\n    this.ogui.updateDisplay();\n    return this.pgui.updateDisplay();\n  };\n\n  FlyCam.prototype.accelerate = function() {\n    var ax, ay, az, ctrl_x, ctrl_y, ctrl_z, sl, sr;\n    sl = this.delta * this.delta * this.sl;\n    sr = this.delta * this.delta * this.sr;\n    ctrl_x = keys.a ? -1 : keys.d ? 1 : 0;\n    ctrl_y = keys.q ? -1 : keys.e ? 1 : 0;\n    ctrl_z = keys.w ? -1 : keys.s ? 1 : 0;\n    ax = ctrl_x * sl;\n    ay = ctrl_y * sl;\n    az = ctrl_z * sl;\n    this.rot.identity().rotatey(-this.o).rotatex(-this.p).mulVal3(ax, ay, az, this.acc);\n    this.x += this.acc.x;\n    this.y += this.acc.y;\n    this.z += this.acc.z;\n    this.o += this.mouse.x * sr;\n    return this.p += this.mouse.y * sr;\n  };\n\n  FlyCam.prototype.move = function() {\n    var o, p, retl, retr, x, y, z;\n    retl = 0.97;\n    retr = 0.94;\n    x = this.x + (this.x - this.lx) * retl;\n    y = this.y + (this.y - this.ly) * retl;\n    z = this.z + (this.z - this.lz) * retl;\n    o = this.o + (this.o - this.lo) * retr;\n    p = this.p + (this.p - this.lp) * retr;\n    if (p > 80) {\n      p = 80;\n    } else if (p < -80) {\n      p = -80;\n    }\n    this.lx = this.x;\n    this.x = x;\n    this.ly = this.y;\n    this.y = y;\n    this.lz = this.z;\n    this.z = z;\n    this.lo = this.o;\n    this.o = o;\n    this.lp = this.p;\n    return this.p = p;\n  };\n\n  FlyCam.prototype.finish = function() {\n    this.mouse.reset();\n    return this.view.identity().rotatex(this.p).rotatey(this.o).translateVal3(-this.x, -this.y, -this.z);\n  };\n\n  return FlyCam;\n\n})(Camera);\n"
  },
  {
    "path": "lib/events.coffee",
    "content": "return class Emitter\n    constructor: ->\n        @handlers = {}\n\n    on: (name, callback) ->\n        handlers = @handlers[name]\n        if handlers == undefined\n            handlers = @handlers[name] = []\n        handlers.push callback\n        return @\n\n    trigger: (name, a1, a2, a3, a4, a5, a6) ->\n        handlers = @handlers[name]\n        if handlers != undefined\n            for handler in handlers\n                handler(a1, a2, a3, a4, a5, a6)\n        return @\n\n"
  },
  {
    "path": "lib/events.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Emitter;\n\nreturn Emitter = (function() {\n\n  function Emitter() {\n    this.handlers = {};\n  }\n\n  Emitter.prototype.on = function(name, callback) {\n    var handlers;\n    handlers = this.handlers[name];\n    if (handlers === void 0) {\n      handlers = this.handlers[name] = [];\n    }\n    handlers.push(callback);\n    return this;\n  };\n\n  Emitter.prototype.trigger = function(name, a1, a2, a3, a4, a5, a6) {\n    var handler, handlers, _i, _len;\n    handlers = this.handlers[name];\n    if (handlers !== void 0) {\n      for (_i = 0, _len = handlers.length; _i < _len; _i++) {\n        handler = handlers[_i];\n        handler(a1, a2, a3, a4, a5, a6);\n      }\n    }\n    return this;\n  };\n\n  return Emitter;\n\n})();\n"
  },
  {
    "path": "lib/geometry.js",
    "content": "// Generated by CoffeeScript 1.3.3\n\nexports.AABB = (function() {\n\n  function AABB(xmin, xmax, ymin, ymax, zmin, zmax) {\n    this.xmin = xmin;\n    this.xmax = xmax;\n    this.ymin = ymin;\n    this.ymax = ymax;\n    this.zmin = zmin;\n    this.zmax = zmax;\n  }\n\n  AABB.prototype.ray_intersect = function(ray) {\n    var d, inv_x, inv_y, inv_z, o, tmax, tmin, ymax, ymin, zmax, zmin, _ref, _ref1, _ref2;\n    o = ray.origin;\n    d = ray.direction;\n    inv_x = 1.0 / d.x;\n    tmin = (this.xmin - o.x) * inv_x;\n    tmax = (this.xmax - o.x) * inv_x;\n    if (inv_x < 0) {\n      _ref = [tmax, tmin], tmin = _ref[0], tmax = _ref[1];\n    }\n    inv_y = 1.0 / d.y;\n    ymin = (this.ymin - o.y) * inv_y;\n    ymax = (this.ymax - o.y) * inv_y;\n    if (inv_y < 0) {\n      _ref1 = [ymax, ymin], ymin = _ref1[0], ymax = _ref1[1];\n    }\n    if (tmin > ymax || ymin > tmax) {\n      return null;\n    }\n    if (ymin > tmin) {\n      tmin = ymin;\n    }\n    if (ymax < tmax) {\n      tmax = ymax;\n    }\n    inv_z = 1.0 / d.z;\n    zmin = (this.zmin - o.z) * inv_z;\n    zmax = (this.zmax - o.z) * inv_z;\n    if (inv_z < 0) {\n      _ref2 = [zmax, zmin], zmin = _ref2[0], zmax = _ref2[1];\n    }\n    if (tmin > zmax || zmin > tmax) {\n      return null;\n    }\n    if (zmin > tmin) {\n      tmin = zmin;\n    }\n    if (zmax < tmax) {\n      tmax = zmax;\n    }\n    return [tmin, tmax];\n  };\n\n  return AABB;\n\n})();\n\nexports.Ray = (function() {\n\n  function Ray(origin, direction) {\n    var _ref, _ref1;\n    this.origin = origin;\n    this.direction = direction;\n    if ((_ref = this.origin) == null) {\n      this.origin = new Vec4();\n    }\n    if ((_ref1 = this.direction) == null) {\n      this.direction = new Vec4();\n    }\n  }\n\n  Ray.prototype.interpolate = function(interval, vector) {\n    var d, o, v;\n    if (vector == null) {\n      vector = new Vec4();\n    }\n    o = this.origin;\n    d = this.direction;\n    v = vector;\n    v.x = o.x + d.x * interval;\n    v.y = o.y + d.y * interval;\n    v.z = o.z + d.z * interval;\n    v.w = o.w + d.w * interval;\n    return vector;\n  };\n\n  Ray.prototype.ray_nearest = function(ray) {\n    var U, V, W, a, b, c, d, det, e, s, t;\n    W = this.origin.sub(ray.origin, new Vec4);\n    U = this.direction;\n    V = ray.direction;\n    a = U.dot(U);\n    b = U.dot(V);\n    c = V.dot(V);\n    d = U.dot(W);\n    e = V.dot(W);\n    det = a * c - b * b;\n    if (det === 0) {\n      return null;\n    }\n    s = (b * e - c * d) / det;\n    t = (a * e - b * d) / det;\n    return [s, t];\n  };\n\n  Ray.prototype.point_distance = function(point) {\n    var W, s;\n    W = point.sub(this.origin, new Vec4);\n    s = W.dot(this.direction) / this.direction.dot(this.direction);\n    W.x -= this.direction.x * s;\n    W.y -= this.direction.y * s;\n    W.z -= this.direction.z * s;\n    return Math.sqrt(W.dot(W));\n  };\n\n  return Ray;\n\n})();\n\nexports.get_mouseray = function(x, y, inv_proj, inv_view, ray) {\n  if (ray == null) {\n    ray = new exports.Ray;\n  }\n  inv_proj.mulVal4(x, y, -1, 1, ray.direction);\n  inv_view.mulVec3(ray.direction);\n  ray.direction.w = 0;\n  inv_view.mulVal4(0, 0, 0, 1, ray.origin);\n  return ray;\n};\n"
  },
  {
    "path": "lib/hdr_clear.shader",
    "content": "vertex:\n    attribute vec2 position;\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform vec4 clear_color;\n    void main(){\n        gl_FragColor = clear_color;\n    }\n"
  },
  {
    "path": "lib/keys.coffee",
    "content": "keymap = ({\n    87: 'w',\n    65: 'a',\n    83: 's',\n    68: 'd',\n    81: 'q',\n    69: 'e',\n    37: 'left',\n    39: 'right',\n    38: 'up',\n    40: 'down',\n    13: 'enter',\n    27: 'esc',\n    32: 'space',\n    8: 'backspace',\n    16: 'shift',\n    17: 'ctrl',\n    18: 'alt',\n    91: 'start',\n    0: 'altc',\n    20: 'caps',\n    9: 'tab',\n    49: 'key1',\n    50: 'key2',\n    51: 'key3',\n    52: 'key4'\n})\n\nkey_handlers = {}\n\nkeys = {\n    press: (name, callback) ->\n        handlers = key_handlers[name] = key_handlers[name] or []\n        handlers.push(callback)\n}\n\n$(document).keydown (event) ->\n    if event.target == document.body\n        name = keymap[event.which]\n        keys[name] = true\n        handlers = key_handlers[name]\n        if handlers\n            for handler in handlers\n                handler()\n\n$(document).keyup (event) ->\n    name = keymap[event.which]\n    keys[name] = false\n\nreturn keys\n"
  },
  {
    "path": "lib/keys.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar key_handlers, keymap, keys;\n\nkeymap = {\n  87: 'w',\n  65: 'a',\n  83: 's',\n  68: 'd',\n  81: 'q',\n  69: 'e',\n  37: 'left',\n  39: 'right',\n  38: 'up',\n  40: 'down',\n  13: 'enter',\n  27: 'esc',\n  32: 'space',\n  8: 'backspace',\n  16: 'shift',\n  17: 'ctrl',\n  18: 'alt',\n  91: 'start',\n  0: 'altc',\n  20: 'caps',\n  9: 'tab',\n  49: 'key1',\n  50: 'key2',\n  51: 'key3',\n  52: 'key4'\n};\n\nkey_handlers = {};\n\nkeys = {\n  press: function(name, callback) {\n    var handlers;\n    handlers = key_handlers[name] = key_handlers[name] || [];\n    return handlers.push(callback);\n  }\n};\n\n$(document).keydown(function(event) {\n  var handler, handlers, name, _i, _len, _results;\n  if (event.target === document.body) {\n    name = keymap[event.which];\n    keys[name] = true;\n    handlers = key_handlers[name];\n    if (handlers) {\n      _results = [];\n      for (_i = 0, _len = handlers.length; _i < _len; _i++) {\n        handler = handlers[_i];\n        _results.push(handler());\n      }\n      return _results;\n    }\n  }\n});\n\n$(document).keyup(function(event) {\n  var name;\n  name = keymap[event.which];\n  return keys[name] = false;\n});\n\nreturn keys;\n"
  },
  {
    "path": "lib/loading.coffee",
    "content": "ui = $('#ui')\nhidden = true\n\ncontainer = $('<div></div>').css\n    position: 'absolute'\n    top: '50%'\n    left: '50%'\n    width: 200\n    height: 40\n    marginLeft: -100\n    marginTop: -20\n\nlabel = $('<div></div>').appendTo(container).css\n    position: 'absolute'\n    top: 0\n    left: 0\n    width: 200\n    height: 20\n    textAlign: 'center'\n    color: 'white'\n\nloading = $('<div></div>').appendTo(container).css\n    position: 'absolute'\n    top: 20\n    left: 0\n    width: 200\n    height: 20\n    border: '1px solid white'\n\nbar = null\nmakeBar = ->\n    loading.empty()\n    bar = $('<div></div>').appendTo(loading).css\n        position: 'absolute'\n        top: 0\n        left: 0\n        width: 0\n        height: 20\n        backgroundColor: 'white'\n        '-webkit-transition': 'width 0.7s'\n\nexports.show = (text) ->\n    label.text text\n    makeBar()\n    container\n        .fadeIn('slow')\n        .appendTo(ui)\n\nexports.hide = ->\n    container.fadeOut 'slow', ->\n        container.detach()\n\nexports.progress = (factor) ->\n    bar.width(factor*200)\n"
  },
  {
    "path": "lib/loading.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar bar, container, hidden, label, loading, makeBar, ui;\n\nui = $('#ui');\n\nhidden = true;\n\ncontainer = $('<div></div>').css({\n  position: 'absolute',\n  top: '50%',\n  left: '50%',\n  width: 200,\n  height: 40,\n  marginLeft: -100,\n  marginTop: -20\n});\n\nlabel = $('<div></div>').appendTo(container).css({\n  position: 'absolute',\n  top: 0,\n  left: 0,\n  width: 200,\n  height: 20,\n  textAlign: 'center',\n  color: 'white'\n});\n\nloading = $('<div></div>').appendTo(container).css({\n  position: 'absolute',\n  top: 20,\n  left: 0,\n  width: 200,\n  height: 20,\n  border: '1px solid white'\n});\n\nbar = null;\n\nmakeBar = function() {\n  loading.empty();\n  return bar = $('<div></div>').appendTo(loading).css({\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    width: 0,\n    height: 20,\n    backgroundColor: 'white',\n    '-webkit-transition': 'width 0.7s'\n  });\n};\n\nexports.show = function(text) {\n  label.text(text);\n  makeBar();\n  return container.fadeIn('slow').appendTo(ui);\n};\n\nexports.hide = function() {\n  return container.fadeOut('slow', function() {\n    return container.detach();\n  });\n};\n\nexports.progress = function(factor) {\n  return bar.width(factor * 200);\n};\n"
  },
  {
    "path": "lib/rendernode.coffee",
    "content": "{Framebuffer, Depthbuffer} = require 'webgl/framebuffer'\n{Texture2D, Cubemap} = require 'webgl/texture'\nQuad = require 'webgl/quad'\n\nclass State\n    constructor: (@gl) ->\n        @depthTest = false\n        @depthWrite = false\n        @cullFace = null\n        @alphaToCoverage = false\n        @blend = false\n\n    setDefaults: ->\n        @gl.disable @gl.DEPTH_TEST\n        @gl.depthMask false\n        @gl.cullFace @gl.BACK\n        @gl.disable @gl.CULL_FACE\n        @gl.disable @gl.SAMPLE_ALPHA_TO_COVERAGE\n        @gl.disable @gl.BLEND\n        return @\n\n    set: ->\n        if @depthTest\n            @gl.enable @gl.DEPTH_TEST\n            mode = @gl[@depthTest]\n            if mode\n                @gl.depthFunc mode\n            else\n                @gl.depthFunc @gl.LEQUAL\n\n        if @depthWrite then @gl.depthMask true\n        if @cullFace\n            @gl.enable @gl.CULL_FACE\n            @gl.cullFace @gl[@cullFace]\n        if @blend\n            @gl.enable @gl.BLEND\n            if @blend == 'additive'\n                @gl.blendFunc @gl.ONE, @gl.ONE\n\n        if @alphaToCoverage then @gl.enable @gl.SAMPLE_ALPHA_TO_COVERAGE\n        return @\n\n    revert: ->\n        if @depthTest\n            @gl.disable @gl.DEPTH_TEST\n            @gl.depthFunc @gl.LESS\n        if @depthWrite then @gl.depthMask false\n        if @cullFace\n            @gl.disable @gl.CULL_FACE\n        if @blend then @gl.disable @gl.BLEND\n        if @alphaToCoverage then @gl.disable @gl.SAMPLE_ALPHA_TO_COVERAGE\n        return @\n        \ndefault_state = null\n\nreturn class Rendernode\n    @stateDefaults = (gl) ->\n        default_state = new State(gl).setDefaults()\n\n    constructor: (@gl, {@width, @height, @program, @drawable, @type, @front, depthTest, depthWrite, cullFace, @depthBuffer, blend, @filter, @channels, @format, @hdrClear}) ->\n        @xoff = 0\n        @yoff = 0\n        @state = new State(@gl)\n        \n        @texunit_counter = 0\n        @texunits = {}\n\n        @type ?= @gl.UNSIGNED_BYTE\n        @front ?= false\n\n        depthTest ?= false\n        @depthTest depthTest\n\n        depthWrite ?= false\n        @depthWrite depthWrite\n\n        cullFace ?= null\n        @cullFace cullFace\n\n        blend ?= false\n        @state.blend = blend\n\n        if not @front\n            @createBuffers()\n\n        if @hdrClear\n            @clearShader = get 'hdr_clear.shader'\n\n    createBuffers: ->\n        @output = new Texture2D(@gl, channels:@channels, format:@format, type:@type).bind().clampToEdge()\n        if @filter == 'nearest'\n            @output.nearest()\n        else\n            @output.linear()\n\n        if @width and @height\n            @output.setSize(@width, @height)\n        else\n            @output.setSize(16, 16)\n        @output.unbind()\n\n        @fbo = new Framebuffer(@gl).bind().color(@output).unbind()\n\n        if @depthBuffer then @addDepth()\n    \n    addDepth: (buffer=@depthBuffer) ->\n        if not @depth and not @front\n            if buffer instanceof Depthbuffer\n                @depth = buffer\n            else\n                @depth = new Depthbuffer(@gl).setSize(@output.width, @output.height)\n            @fbo.bind().depth(@depth).unbind()\n        return @\n\n    cullFace: (side=null) ->\n        @state.cullFace = side\n        return @\n\n    depthWrite: (enabled=false) ->\n        @state.depthWrite = enabled\n        return @\n\n    depthTest: (enabled=false) ->\n        @state.depthTest = enabled\n        return @\n\n    alphaToCoverage: (enabled=false) ->\n        @state.alphaToCoverage = enabled\n        return @\n\n    blendAdditive: ->\n        @state.blend = 'additive'\n        return @\n\n    filterNearest: ->\n        @output.bind().nearest().unbind()\n        return @\n\n    start: ->\n        @started = true\n        @viewport()\n        @state.set()\n        if @program then @program.use()\n        if not @front then @fbo.bind()\n        if @drawable then @setPointers @drawable\n        return @\n\n    setPointers: (drawable) ->\n        if drawable != @current_drawable\n            @current_drawable = drawable\n            drawable.setPointersForShader @program\n    \n    end: ->\n        @started = false\n        @current_drawable = null\n        @state.revert()\n        if not @front then @fbo.unbind()\n        return @\n\n    sampler: (name, source) ->\n        if source.output\n            texture = source.output\n        else\n            texture = source\n\n        unit = @texunits[name]\n        if unit == undefined\n            unit = @texunits[name] = @texunit_counter++\n        texture.bind(unit)\n        @program.i name, unit\n        return @\n\n    mat4: (name, value) ->\n        @program.mat4(name, value)\n        return @\n    \n    mat3: (name, value) ->\n        @program.mat3(name, value)\n        return @\n\n    val3: (name, x, y, z) ->\n        @program.val3(name, x, y, z)\n        return @\n    \n    vec3: (name, value) ->\n        @program.vec3(name, value)\n        return @\n\n    f: (name, value) ->\n        @program.f name, value\n        return @\n\n    fv: (name, values) ->\n        @program.fv name, values\n        return @\n\n    val2: (name, x, y) ->\n        @program.val2(name, x, y)\n        return @\n\n    clear: (r=0, g=0, b=0, a=1) ->\n        if @hdrClear\n            if not @front then @fbo.bind()\n            @clearShader.use().val4('clear_color', r, g, b, a).draw(quad)\n        else\n            @gl.clearColor r, g, b, a\n            @gl.clear @gl.COLOR_BUFFER_BIT\n        return @\n\n    clearBoth: (r=0, g=0, b=0, a=1, depth=1) ->\n        @gl.clearColor r, g, b, a\n        @gl.clearDepth depth\n        @gl.clear @gl.COLOR_BUFFER_BIT | @gl.DEPTH_BUFFER_BIT\n        return @\n\n    clearDepth: (depth=1) ->\n        @gl.clearDepth depth\n        @gl.clear @gl.DEPTH_BUFFER_BIT\n        return @\n\n    draw: (drawable=@drawable) ->\n        do_end = false\n        if not @started\n            do_end = true\n            @start()\n\n        @program.val2 'viewport', @width, @height\n        if drawable != @current_drawable\n            @setPointers drawable\n        drawable.draw()\n\n        if do_end\n            @end()\n\n        return @\n\n    drawModel: (texture_type, sampler_name=texture_type) ->\n        if texture_type\n            for material in @drawable.materials[texture_type]\n                @f('specularity', material.specularity)\n                c = material.diffuse_color\n                @val3('diffuse_color', c.r, c.g, c.b)\n                @sampler(sampler_name, material[texture_type])\n                @drawable.drawRange material.start, material.size\n        else\n            @draw()\n        return @\n\n    resize: (width, height) ->\n        @width = Math.floor(width)\n        @height = Math.floor(height)\n        if @output\n            @output.bind()\n                .setSize(@width, @height)\n                .unbind()\n\n        if @depth\n            @depth.setSize(@width, @height)\n\n        if @fbo\n            @fbo.bind().check().unbind()\n\n    viewport: (x=@xoff, y=@yoff, width=@width, height=@height) ->\n        if width and height\n            @xoff = x\n            @yoff = y\n            @width = width\n            @height = height\n            if @started\n                @gl.viewport x, y, width, height\n            return @\n\n    bind: (unit=0) ->\n        @output.bind(unit)\n"
  },
  {
    "path": "lib/rendernode.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Cubemap, Depthbuffer, Framebuffer, Quad, Rendernode, State, Texture2D, default_state, _ref, _ref1;\n\n_ref = require('webgl/framebuffer'), Framebuffer = _ref.Framebuffer, Depthbuffer = _ref.Depthbuffer;\n\n_ref1 = require('webgl/texture'), Texture2D = _ref1.Texture2D, Cubemap = _ref1.Cubemap;\n\nQuad = require('webgl/quad');\n\nState = (function() {\n\n  function State(gl) {\n    this.gl = gl;\n    this.depthTest = false;\n    this.depthWrite = false;\n    this.cullFace = null;\n    this.alphaToCoverage = false;\n    this.blend = false;\n  }\n\n  State.prototype.setDefaults = function() {\n    this.gl.disable(this.gl.DEPTH_TEST);\n    this.gl.depthMask(false);\n    this.gl.cullFace(this.gl.BACK);\n    this.gl.disable(this.gl.CULL_FACE);\n    this.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    this.gl.disable(this.gl.BLEND);\n    return this;\n  };\n\n  State.prototype.set = function() {\n    var mode;\n    if (this.depthTest) {\n      this.gl.enable(this.gl.DEPTH_TEST);\n      mode = this.gl[this.depthTest];\n      if (mode) {\n        this.gl.depthFunc(mode);\n      } else {\n        this.gl.depthFunc(this.gl.LEQUAL);\n      }\n    }\n    if (this.depthWrite) {\n      this.gl.depthMask(true);\n    }\n    if (this.cullFace) {\n      this.gl.enable(this.gl.CULL_FACE);\n      this.gl.cullFace(this.gl[this.cullFace]);\n    }\n    if (this.blend) {\n      this.gl.enable(this.gl.BLEND);\n      if (this.blend === 'additive') {\n        this.gl.blendFunc(this.gl.ONE, this.gl.ONE);\n      }\n    }\n    if (this.alphaToCoverage) {\n      this.gl.enable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    }\n    return this;\n  };\n\n  State.prototype.revert = function() {\n    if (this.depthTest) {\n      this.gl.disable(this.gl.DEPTH_TEST);\n      this.gl.depthFunc(this.gl.LESS);\n    }\n    if (this.depthWrite) {\n      this.gl.depthMask(false);\n    }\n    if (this.cullFace) {\n      this.gl.disable(this.gl.CULL_FACE);\n    }\n    if (this.blend) {\n      this.gl.disable(this.gl.BLEND);\n    }\n    if (this.alphaToCoverage) {\n      this.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    }\n    return this;\n  };\n\n  return State;\n\n})();\n\ndefault_state = null;\n\nreturn Rendernode = (function() {\n\n  Rendernode.stateDefaults = function(gl) {\n    return default_state = new State(gl).setDefaults();\n  };\n\n  function Rendernode(gl, _arg) {\n    var blend, cullFace, depthTest, depthWrite, _ref2, _ref3;\n    this.gl = gl;\n    this.width = _arg.width, this.height = _arg.height, this.program = _arg.program, this.drawable = _arg.drawable, this.type = _arg.type, this.front = _arg.front, depthTest = _arg.depthTest, depthWrite = _arg.depthWrite, cullFace = _arg.cullFace, this.depthBuffer = _arg.depthBuffer, blend = _arg.blend, this.filter = _arg.filter, this.channels = _arg.channels, this.format = _arg.format, this.hdrClear = _arg.hdrClear;\n    this.xoff = 0;\n    this.yoff = 0;\n    this.state = new State(this.gl);\n    this.texunit_counter = 0;\n    this.texunits = {};\n    if ((_ref2 = this.type) == null) {\n      this.type = this.gl.UNSIGNED_BYTE;\n    }\n    if ((_ref3 = this.front) == null) {\n      this.front = false;\n    }\n    if (depthTest == null) {\n      depthTest = false;\n    }\n    this.depthTest(depthTest);\n    if (depthWrite == null) {\n      depthWrite = false;\n    }\n    this.depthWrite(depthWrite);\n    if (cullFace == null) {\n      cullFace = null;\n    }\n    this.cullFace(cullFace);\n    if (blend == null) {\n      blend = false;\n    }\n    this.state.blend = blend;\n    if (!this.front) {\n      this.createBuffers();\n    }\n    if (this.hdrClear) {\n      this.clearShader = get('hdr_clear.shader');\n    }\n  }\n\n  Rendernode.prototype.createBuffers = function() {\n    this.output = new Texture2D(this.gl, {\n      channels: this.channels,\n      format: this.format,\n      type: this.type\n    }).bind().clampToEdge();\n    if (this.filter === 'nearest') {\n      this.output.nearest();\n    } else {\n      this.output.linear();\n    }\n    if (this.width && this.height) {\n      this.output.setSize(this.width, this.height);\n    } else {\n      this.output.setSize(16, 16);\n    }\n    this.output.unbind();\n    this.fbo = new Framebuffer(this.gl).bind().color(this.output).unbind();\n    if (this.depthBuffer) {\n      return this.addDepth();\n    }\n  };\n\n  Rendernode.prototype.addDepth = function(buffer) {\n    if (buffer == null) {\n      buffer = this.depthBuffer;\n    }\n    if (!this.depth && !this.front) {\n      if (buffer instanceof Depthbuffer) {\n        this.depth = buffer;\n      } else {\n        this.depth = new Depthbuffer(this.gl).setSize(this.output.width, this.output.height);\n      }\n      this.fbo.bind().depth(this.depth).unbind();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.cullFace = function(side) {\n    if (side == null) {\n      side = null;\n    }\n    this.state.cullFace = side;\n    return this;\n  };\n\n  Rendernode.prototype.depthWrite = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.depthWrite = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.depthTest = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.depthTest = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.alphaToCoverage = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.alphaToCoverage = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.blendAdditive = function() {\n    this.state.blend = 'additive';\n    return this;\n  };\n\n  Rendernode.prototype.filterNearest = function() {\n    this.output.bind().nearest().unbind();\n    return this;\n  };\n\n  Rendernode.prototype.start = function() {\n    this.started = true;\n    this.viewport();\n    this.state.set();\n    if (this.program) {\n      this.program.use();\n    }\n    if (!this.front) {\n      this.fbo.bind();\n    }\n    if (this.drawable) {\n      this.setPointers(this.drawable);\n    }\n    return this;\n  };\n\n  Rendernode.prototype.setPointers = function(drawable) {\n    if (drawable !== this.current_drawable) {\n      this.current_drawable = drawable;\n      return drawable.setPointersForShader(this.program);\n    }\n  };\n\n  Rendernode.prototype.end = function() {\n    this.started = false;\n    this.current_drawable = null;\n    this.state.revert();\n    if (!this.front) {\n      this.fbo.unbind();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.sampler = function(name, source) {\n    var texture, unit;\n    if (source.output) {\n      texture = source.output;\n    } else {\n      texture = source;\n    }\n    unit = this.texunits[name];\n    if (unit === void 0) {\n      unit = this.texunits[name] = this.texunit_counter++;\n    }\n    texture.bind(unit);\n    this.program.i(name, unit);\n    return this;\n  };\n\n  Rendernode.prototype.mat4 = function(name, value) {\n    this.program.mat4(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.mat3 = function(name, value) {\n    this.program.mat3(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.val3 = function(name, x, y, z) {\n    this.program.val3(name, x, y, z);\n    return this;\n  };\n\n  Rendernode.prototype.vec3 = function(name, value) {\n    this.program.vec3(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.f = function(name, value) {\n    this.program.f(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.fv = function(name, values) {\n    this.program.fv(name, values);\n    return this;\n  };\n\n  Rendernode.prototype.val2 = function(name, x, y) {\n    this.program.val2(name, x, y);\n    return this;\n  };\n\n  Rendernode.prototype.clear = function(r, g, b, a) {\n    if (r == null) {\n      r = 0;\n    }\n    if (g == null) {\n      g = 0;\n    }\n    if (b == null) {\n      b = 0;\n    }\n    if (a == null) {\n      a = 1;\n    }\n    if (this.hdrClear) {\n      if (!this.front) {\n        this.fbo.bind();\n      }\n      this.clearShader.use().val4('clear_color', r, g, b, a).draw(quad);\n    } else {\n      this.gl.clearColor(r, g, b, a);\n      this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n    }\n    return this;\n  };\n\n  Rendernode.prototype.clearBoth = function(r, g, b, a, depth) {\n    if (r == null) {\n      r = 0;\n    }\n    if (g == null) {\n      g = 0;\n    }\n    if (b == null) {\n      b = 0;\n    }\n    if (a == null) {\n      a = 1;\n    }\n    if (depth == null) {\n      depth = 1;\n    }\n    this.gl.clearColor(r, g, b, a);\n    this.gl.clearDepth(depth);\n    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n    return this;\n  };\n\n  Rendernode.prototype.clearDepth = function(depth) {\n    if (depth == null) {\n      depth = 1;\n    }\n    this.gl.clearDepth(depth);\n    this.gl.clear(this.gl.DEPTH_BUFFER_BIT);\n    return this;\n  };\n\n  Rendernode.prototype.draw = function(drawable) {\n    var do_end;\n    if (drawable == null) {\n      drawable = this.drawable;\n    }\n    do_end = false;\n    if (!this.started) {\n      do_end = true;\n      this.start();\n    }\n    this.program.val2('viewport', this.width, this.height);\n    if (drawable !== this.current_drawable) {\n      this.setPointers(drawable);\n    }\n    drawable.draw();\n    if (do_end) {\n      this.end();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.drawModel = function(texture_type, sampler_name) {\n    var c, material, _i, _len, _ref2;\n    if (sampler_name == null) {\n      sampler_name = texture_type;\n    }\n    if (texture_type) {\n      _ref2 = this.drawable.materials[texture_type];\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        material = _ref2[_i];\n        this.f('specularity', material.specularity);\n        c = material.diffuse_color;\n        this.val3('diffuse_color', c.r, c.g, c.b);\n        this.sampler(sampler_name, material[texture_type]);\n        this.drawable.drawRange(material.start, material.size);\n      }\n    } else {\n      this.draw();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.resize = function(width, height) {\n    this.width = Math.floor(width);\n    this.height = Math.floor(height);\n    if (this.output) {\n      this.output.bind().setSize(this.width, this.height).unbind();\n    }\n    if (this.depth) {\n      this.depth.setSize(this.width, this.height);\n    }\n    if (this.fbo) {\n      return this.fbo.bind().check().unbind();\n    }\n  };\n\n  Rendernode.prototype.viewport = function(x, y, width, height) {\n    if (x == null) {\n      x = this.xoff;\n    }\n    if (y == null) {\n      y = this.yoff;\n    }\n    if (width == null) {\n      width = this.width;\n    }\n    if (height == null) {\n      height = this.height;\n    }\n    if (width && height) {\n      this.xoff = x;\n      this.yoff = y;\n      this.width = width;\n      this.height = height;\n      if (this.started) {\n        this.gl.viewport(x, y, width, height);\n      }\n      return this;\n    }\n  };\n\n  Rendernode.prototype.bind = function(unit) {\n    if (unit == null) {\n      unit = 0;\n    }\n    return this.output.bind(unit);\n  };\n\n  return Rendernode;\n\n})();\n"
  },
  {
    "path": "lib/schedule.coffee",
    "content": "exports.run = (callback) ->\n    last = gettime()\n\n    step = ->\n        current = gettime()\n        delta = current-last\n        last = current\n        callback current, delta\n        requestAnimationFrame step\n\n    requestAnimationFrame step\n"
  },
  {
    "path": "lib/schedule.js",
    "content": "// Generated by CoffeeScript 1.3.3\n\nexports.run = function(callback) {\n  var last, step;\n  last = gettime();\n  step = function() {\n    var current, delta;\n    current = gettime();\n    delta = current - last;\n    last = current;\n    callback(current, delta);\n    return requestAnimationFrame(step);\n  };\n  return requestAnimationFrame(step);\n};\n"
  },
  {
    "path": "lib/webgl/cube.coffee",
    "content": "return class Cube extends require('drawable')\n    attribs: ['position', 'normal', 'barycentric']\n    pointers: [\n        {name: 'position',      size: 3, offset: 0, stride: 9},\n        {name: 'normal',        size: 3, offset: 3, stride: 9},\n        {name: 'barycentric',   size: 3, offset: 6, stride: 9},\n    ]\n\n    constructor: (@gl, s=1) ->\n        super()\n        @size = 6 * 6\n        vertices = [\n            -s, -s, -s,  0,  0, -1, 1,0,0,\n            -s,  s, -s,  0,  0, -1, 0,1,0,\n             s,  s, -s,  0,  0, -1, 0,0,1,\n             s, -s, -s,  0,  0, -1, 1,0,0,\n            -s, -s, -s,  0,  0, -1, 0,1,0,\n             s,  s, -s,  0,  0, -1, 0,0,1,\n                                   \n             s,  s,  s,  0,  0,  1, 1,0,0,\n            -s,  s,  s,  0,  0,  1, 0,1,0,\n            -s, -s,  s,  0,  0,  1, 0,0,1,\n             s,  s,  s,  0,  0,  1, 1,0,0,\n            -s, -s,  s,  0,  0,  1, 0,1,0,\n             s, -s,  s,  0,  0,  1, 0,0,1,\n                                   \n            -s,  s, -s,  0,  1,  0, 1,0,0,\n            -s,  s,  s,  0,  1,  0, 0,1,0,\n             s,  s,  s,  0,  1,  0, 0,0,1,\n             s,  s, -s,  0,  1,  0, 1,0,0,\n            -s,  s, -s,  0,  1,  0, 0,1,0,\n             s,  s,  s,  0,  1,  0, 0,0,1,\n                                   \n             s, -s,  s,  0, -1,  0, 1,0,0,\n            -s, -s,  s,  0, -1,  0, 0,1,0,\n            -s, -s, -s,  0, -1,  0, 0,0,1,\n             s, -s,  s,  0, -1,  0, 1,0,0,\n            -s, -s, -s,  0, -1,  0, 0,1,0,\n             s, -s, -s,  0, -1,  0, 0,0,1,\n                                   \n            -s, -s, -s, -1,  0,  0, 1,0,0,\n            -s, -s,  s, -1,  0,  0, 0,1,0,\n            -s,  s,  s, -1,  0,  0, 0,0,1,\n            -s,  s, -s, -1,  0,  0, 1,0,0,\n            -s, -s, -s, -1,  0,  0, 0,1,0,\n            -s,  s,  s, -1,  0,  0, 0,0,1,\n                                   \n             s,  s,  s,  1,  0,  0, 1,0,0,\n             s, -s,  s,  1,  0,  0, 0,1,0,\n             s, -s, -s,  1,  0,  0, 0,0,1,\n             s,  s,  s,  1,  0,  0, 1,0,0,\n             s, -s, -s,  1,  0,  0, 0,1,0,\n             s,  s, -s,  1,  0,  0, 0,0,1,\n        ]\n\n        @uploadList vertices\n"
  },
  {
    "path": "lib/webgl/cube.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Cube,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Cube = (function(_super) {\n\n  __extends(Cube, _super);\n\n  Cube.prototype.attribs = ['position', 'normal', 'barycentric'];\n\n  Cube.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 9\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 3,\n      stride: 9\n    }, {\n      name: 'barycentric',\n      size: 3,\n      offset: 6,\n      stride: 9\n    }\n  ];\n\n  function Cube(gl, s) {\n    var vertices;\n    this.gl = gl;\n    if (s == null) {\n      s = 1;\n    }\n    Cube.__super__.constructor.call(this);\n    this.size = 6 * 6;\n    vertices = [-s, -s, -s, 0, 0, -1, 1, 0, 0, -s, s, -s, 0, 0, -1, 0, 1, 0, s, s, -s, 0, 0, -1, 0, 0, 1, s, -s, -s, 0, 0, -1, 1, 0, 0, -s, -s, -s, 0, 0, -1, 0, 1, 0, s, s, -s, 0, 0, -1, 0, 0, 1, s, s, s, 0, 0, 1, 1, 0, 0, -s, s, s, 0, 0, 1, 0, 1, 0, -s, -s, s, 0, 0, 1, 0, 0, 1, s, s, s, 0, 0, 1, 1, 0, 0, -s, -s, s, 0, 0, 1, 0, 1, 0, s, -s, s, 0, 0, 1, 0, 0, 1, -s, s, -s, 0, 1, 0, 1, 0, 0, -s, s, s, 0, 1, 0, 0, 1, 0, s, s, s, 0, 1, 0, 0, 0, 1, s, s, -s, 0, 1, 0, 1, 0, 0, -s, s, -s, 0, 1, 0, 0, 1, 0, s, s, s, 0, 1, 0, 0, 0, 1, s, -s, s, 0, -1, 0, 1, 0, 0, -s, -s, s, 0, -1, 0, 0, 1, 0, -s, -s, -s, 0, -1, 0, 0, 0, 1, s, -s, s, 0, -1, 0, 1, 0, 0, -s, -s, -s, 0, -1, 0, 0, 1, 0, s, -s, -s, 0, -1, 0, 0, 0, 1, -s, -s, -s, -1, 0, 0, 1, 0, 0, -s, -s, s, -1, 0, 0, 0, 1, 0, -s, s, s, -1, 0, 0, 0, 0, 1, -s, s, -s, -1, 0, 0, 1, 0, 0, -s, -s, -s, -1, 0, 0, 0, 1, 0, -s, s, s, -1, 0, 0, 0, 0, 1, s, s, s, 1, 0, 0, 1, 0, 0, s, -s, s, 1, 0, 0, 0, 1, 0, s, -s, -s, 1, 0, 0, 0, 0, 1, s, s, s, 1, 0, 0, 1, 0, 0, s, -s, -s, 1, 0, 0, 0, 1, 0, s, s, -s, 1, 0, 0, 0, 0, 1];\n    this.uploadList(vertices);\n  }\n\n  return Cube;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/drawable.coffee",
    "content": "return class Drawable\n    float_size = Float32Array.BYTES_PER_ELEMENT\n\n    constructor: () ->\n        @first = 0\n        @size = 0\n        @buffer = @gl.createBuffer()\n        @mode = @gl.TRIANGLES\n\n    setPointer: (shader, name, size=3, start=0, stride=0) ->\n        location = shader.attribLoc name\n        if location >= 0\n            @gl.vertexAttribPointer location, size, @gl.FLOAT, false, stride*float_size, start*float_size\n        return @\n    \n    setPointersForShader: (shader) ->\n        @gl.bindBuffer @gl.ARRAY_BUFFER, @buffer\n        for pointer in @pointers\n            @setPointer shader, pointer.name, pointer.size, pointer.offset, pointer.stride\n        return @\n    \n    draw: (shader) ->\n        if shader then @setPointersForShader shader\n        @gl.drawArrays @mode, @first, @size\n        if shader then @disableAttribs shader\n        return @\n\n    drawRange: (start=@first, size=@size) ->\n        @gl.drawArrays @mode, start, size\n\n    disableAttribs: (shader) ->\n        for name in @attribs\n            location = shader.attribLoc name\n            if location >= 0 then @gl.disableVertexAttribArray location\n        return @\n\n    uploadList: (list) ->\n        data = new Float32Array list\n        @upload data\n      \n    upload: (data) ->\n        @gl.bindBuffer @gl.ARRAY_BUFFER, @buffer\n        @gl.bufferData @gl.ARRAY_BUFFER, data, @gl.STATIC_DRAW\n        @gl.bindBuffer @gl.ARRAY_BUFFER, null\n"
  },
  {
    "path": "lib/webgl/drawable.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Drawable;\n\nreturn Drawable = (function() {\n  var float_size;\n\n  float_size = Float32Array.BYTES_PER_ELEMENT;\n\n  function Drawable() {\n    this.first = 0;\n    this.size = 0;\n    this.buffer = this.gl.createBuffer();\n    this.mode = this.gl.TRIANGLES;\n  }\n\n  Drawable.prototype.setPointer = function(shader, name, size, start, stride) {\n    var location;\n    if (size == null) {\n      size = 3;\n    }\n    if (start == null) {\n      start = 0;\n    }\n    if (stride == null) {\n      stride = 0;\n    }\n    location = shader.attribLoc(name);\n    if (location >= 0) {\n      this.gl.vertexAttribPointer(location, size, this.gl.FLOAT, false, stride * float_size, start * float_size);\n    }\n    return this;\n  };\n\n  Drawable.prototype.setPointersForShader = function(shader) {\n    var pointer, _i, _len, _ref;\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    _ref = this.pointers;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      pointer = _ref[_i];\n      this.setPointer(shader, pointer.name, pointer.size, pointer.offset, pointer.stride);\n    }\n    return this;\n  };\n\n  Drawable.prototype.draw = function(shader) {\n    if (shader) {\n      this.setPointersForShader(shader);\n    }\n    this.gl.drawArrays(this.mode, this.first, this.size);\n    if (shader) {\n      this.disableAttribs(shader);\n    }\n    return this;\n  };\n\n  Drawable.prototype.drawRange = function(start, size) {\n    if (start == null) {\n      start = this.first;\n    }\n    if (size == null) {\n      size = this.size;\n    }\n    return this.gl.drawArrays(this.mode, start, size);\n  };\n\n  Drawable.prototype.disableAttribs = function(shader) {\n    var location, name, _i, _len, _ref;\n    _ref = this.attribs;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      name = _ref[_i];\n      location = shader.attribLoc(name);\n      if (location >= 0) {\n        this.gl.disableVertexAttribArray(location);\n      }\n    }\n    return this;\n  };\n\n  Drawable.prototype.uploadList = function(list) {\n    var data;\n    data = new Float32Array(list);\n    return this.upload(data);\n  };\n\n  Drawable.prototype.upload = function(data) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.gl.bufferData(this.gl.ARRAY_BUFFER, data, this.gl.STATIC_DRAW);\n    return this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n  };\n\n  return Drawable;\n\n})();\n"
  },
  {
    "path": "lib/webgl/framebuffer.coffee",
    "content": "framebufferBinding = null\n\nexports.Framebuffer = class Framebuffer\n    constructor: (@gl) ->\n        @buffer = @gl.createFramebuffer()\n\n    bind: ->\n        if framebufferBinding isnt @\n            @gl.bindFramebuffer @gl.FRAMEBUFFER, @buffer\n            framebufferBinding = @\n\n        return @\n\n    unbind: ->\n        if framebufferBinding isnt null\n            @gl.bindFramebuffer @gl.FRAMEBUFFER, null\n            framebufferBinding = null\n\n        return @\n\n    check: ->\n        result = @gl.checkFramebufferStatus @gl.FRAMEBUFFER\n        switch result\n            when @gl.FRAMEBUFFER_UNSUPPORTED\n                throw 'Framebuffer is unsupported'\n            when @gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n                throw 'Framebuffer incomplete attachment'\n            when @gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS\n                throw 'Framebuffer incomplete dimensions'\n            when @gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n                throw 'Framebuffer incomplete missing attachment'\n        return @\n\n    color: (texture, target=texture.target) ->\n        @gl.framebufferTexture2D @gl.FRAMEBUFFER, @gl.COLOR_ATTACHMENT0, target, texture.handle, 0\n        @check()\n        return @\n        \n    depth: (buffer) ->\n        @gl.framebufferRenderbuffer @gl.FRAMEBUFFER, @gl.DEPTH_ATTACHMENT, @gl.RENDERBUFFER, buffer.id\n        @check()\n        return @\n\n    destroy: ->\n        @gl.deleteFramebuffer @buffer\n\nclass Renderbuffer\n    constructor: (@gl) ->\n        @id = @gl.createRenderbuffer()\n\n    bind: ->\n        @gl.bindRenderbuffer @gl.RENDERBUFFER, @id\n        return @\n\n    setSize: (@width, @height) ->\n        @bind()\n        @gl.renderbufferStorage @gl.RENDERBUFFER, @gl[@format], @width, @height\n        @unbind()\n\n    unbind: ->\n        @gl.bindRenderbuffer @gl.RENDERBUFFER, null\n        return @\n\nexports.Depthbuffer = class extends Renderbuffer\n    format: 'DEPTH_COMPONENT16'\n"
  },
  {
    "path": "lib/webgl/framebuffer.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Framebuffer, Renderbuffer, framebufferBinding,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nframebufferBinding = null;\n\nexports.Framebuffer = Framebuffer = (function() {\n\n  function Framebuffer(gl) {\n    this.gl = gl;\n    this.buffer = this.gl.createFramebuffer();\n  }\n\n  Framebuffer.prototype.bind = function() {\n    if (framebufferBinding !== this) {\n      this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.buffer);\n      framebufferBinding = this;\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.unbind = function() {\n    if (framebufferBinding !== null) {\n      this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n      framebufferBinding = null;\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.check = function() {\n    var result;\n    result = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);\n    switch (result) {\n      case this.gl.FRAMEBUFFER_UNSUPPORTED:\n        throw 'Framebuffer is unsupported';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\n        throw 'Framebuffer incomplete attachment';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:\n        throw 'Framebuffer incomplete dimensions';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\n        throw 'Framebuffer incomplete missing attachment';\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.color = function(texture, target) {\n    if (target == null) {\n      target = texture.target;\n    }\n    this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, target, texture.handle, 0);\n    this.check();\n    return this;\n  };\n\n  Framebuffer.prototype.depth = function(buffer) {\n    this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, buffer.id);\n    this.check();\n    return this;\n  };\n\n  Framebuffer.prototype.destroy = function() {\n    return this.gl.deleteFramebuffer(this.buffer);\n  };\n\n  return Framebuffer;\n\n})();\n\nRenderbuffer = (function() {\n\n  function Renderbuffer(gl) {\n    this.gl = gl;\n    this.id = this.gl.createRenderbuffer();\n  }\n\n  Renderbuffer.prototype.bind = function() {\n    this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.id);\n    return this;\n  };\n\n  Renderbuffer.prototype.setSize = function(width, height) {\n    this.width = width;\n    this.height = height;\n    this.bind();\n    this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl[this.format], this.width, this.height);\n    return this.unbind();\n  };\n\n  Renderbuffer.prototype.unbind = function() {\n    this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);\n    return this;\n  };\n\n  return Renderbuffer;\n\n})();\n\nexports.Depthbuffer = (function(_super) {\n\n  __extends(_Class, _super);\n\n  function _Class() {\n    return _Class.__super__.constructor.apply(this, arguments);\n  }\n\n  _Class.prototype.format = 'DEPTH_COMPONENT16';\n\n  return _Class;\n\n})(Renderbuffer);\n"
  },
  {
    "path": "lib/webgl/hexgrid.coffee",
    "content": "clamp = (value, left, right) ->\n    return if value < left then left else if value > right then right else value\n\nreturn class Hexgrid extends require('drawable')\n    attribs: ['position', 'texcoord', 'barycentric']\n\n    constructor: (@gl, xsize=16, ysize=16, width=1, height=1) ->\n        super()\n        vertices = []\n\n        for x in [0..xsize]\n            x1 = clamp((x-0.5)/xsize, 0, 1)\n            x2 = clamp((x+0.0)/xsize, 0, 1)\n            x3 = clamp((x+0.5)/xsize, 0, 1)\n            x4 = clamp((x+1.0)/xsize, 0, 1)\n            for y in [0...ysize] by 2\n                t = (y+0)/ysize\n                m = (y+1)/ysize\n                b = (y+2)/ysize\n\n                vertices.push(\n                    x2*width,0,m*height, x2,m, 0,0,1,\n                    x3*width,0,t*height, x3,t, 0,1,0,\n                    x1*width,0,t*height, x1,t, 1,0,0,\n\n                    x4*width,0,m*height, x4,m, 0,0,1,\n                    x3*width,0,t*height, x3,t, 0,1,0,\n                    x2*width,0,m*height, x2,m, 1,0,0,\n                    \n                    x3*width,0,b*height, x3,b, 0,0,1,\n                    x2*width,0,m*height, x2,m, 0,1,0,\n                    x1*width,0,b*height, x1,b, 1,0,0,\n                    \n                    x3*width,0,b*height, x3,b, 0,0,1\n                    x4*width,0,m*height, x4,m, 0,1,0,\n                    x2*width,0,m*height, x2,m, 1,0,0,\n                )\n        @size = vertices.length/8\n        @uploadList vertices\n\n    setPointersForShader: (shader) ->\n        @gl.bindBuffer @gl.ARRAY_BUFFER, @buffer\n        @setPointer shader, 'position', 3, 0, 8\n        @setPointer shader, 'texcoord', 2, 3, 8\n        @setPointer shader, 'barycentric', 3, 5, 8\n\n        return @\n"
  },
  {
    "path": "lib/webgl/hexgrid.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Hexgrid, clamp,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nclamp = function(value, left, right) {\n  if (value < left) {\n    return left;\n  } else if (value > right) {\n    return right;\n  } else {\n    return value;\n  }\n};\n\nreturn Hexgrid = (function(_super) {\n\n  __extends(Hexgrid, _super);\n\n  Hexgrid.prototype.attribs = ['position', 'texcoord', 'barycentric'];\n\n  function Hexgrid(gl, xsize, ysize, width, height) {\n    var b, m, t, vertices, x, x1, x2, x3, x4, y, _i, _j;\n    this.gl = gl;\n    if (xsize == null) {\n      xsize = 16;\n    }\n    if (ysize == null) {\n      ysize = 16;\n    }\n    if (width == null) {\n      width = 1;\n    }\n    if (height == null) {\n      height = 1;\n    }\n    Hexgrid.__super__.constructor.call(this);\n    vertices = [];\n    for (x = _i = 0; 0 <= xsize ? _i <= xsize : _i >= xsize; x = 0 <= xsize ? ++_i : --_i) {\n      x1 = clamp((x - 0.5) / xsize, 0, 1);\n      x2 = clamp((x + 0.0) / xsize, 0, 1);\n      x3 = clamp((x + 0.5) / xsize, 0, 1);\n      x4 = clamp((x + 1.0) / xsize, 0, 1);\n      for (y = _j = 0; _j < ysize; y = _j += 2) {\n        t = (y + 0) / ysize;\n        m = (y + 1) / ysize;\n        b = (y + 2) / ysize;\n        vertices.push(x2 * width, 0, m * height, x2, m, 0, 0, 1, x3 * width, 0, t * height, x3, t, 0, 1, 0, x1 * width, 0, t * height, x1, t, 1, 0, 0, x4 * width, 0, m * height, x4, m, 0, 0, 1, x3 * width, 0, t * height, x3, t, 0, 1, 0, x2 * width, 0, m * height, x2, m, 1, 0, 0, x3 * width, 0, b * height, x3, b, 0, 0, 1, x2 * width, 0, m * height, x2, m, 0, 1, 0, x1 * width, 0, b * height, x1, b, 1, 0, 0, x3 * width, 0, b * height, x3, b, 0, 0, 1, x4 * width, 0, m * height, x4, m, 0, 1, 0, x2 * width, 0, m * height, x2, m, 1, 0, 0);\n      }\n    }\n    this.size = vertices.length / 8;\n    this.uploadList(vertices);\n  }\n\n  Hexgrid.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'texcoord', 2, 3, 8);\n    this.setPointer(shader, 'barycentric', 3, 5, 8);\n    return this;\n  };\n\n  return Hexgrid;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/model.coffee",
    "content": "return class Model extends require('drawable')\n    attribs: ['position', 'normal', 'texcoord']\n\n    constructor: (@gl, data) ->\n        super()\n        @size = data.byteLength/(8*Float32Array.BYTES_PER_ELEMENT)\n        @upload data\n\n    setPointersForShader: (shader) ->\n        @gl.bindBuffer @gl.ARRAY_BUFFER, @buffer\n        @setPointer shader, 'position', 3, 0, 8\n        @setPointer shader, 'normal', 3, 3, 8\n        @setPointer shader, 'texcoord', 2, 6, 8\n\n        return @\n"
  },
  {
    "path": "lib/webgl/model.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Model,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Model = (function(_super) {\n\n  __extends(Model, _super);\n\n  Model.prototype.attribs = ['position', 'normal', 'texcoord'];\n\n  function Model(gl, data) {\n    this.gl = gl;\n    Model.__super__.constructor.call(this);\n    this.size = data.byteLength / (8 * Float32Array.BYTES_PER_ELEMENT);\n    this.upload(data);\n  }\n\n  Model.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'normal', 3, 3, 8);\n    this.setPointer(shader, 'texcoord', 2, 6, 8);\n    return this;\n  };\n\n  return Model;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/plane.coffee",
    "content": "return class Plane extends require('drawable')\n    attribs: ['position', 'normal', 'texcoord']\n\n    constructor: (@gl, s=1) ->\n        super()\n        @size = 6\n\n        vertices = [\n            -s,  0, -s,  0,  1,  0,  0,0,\n            -s,  0,  s,  0,  1,  0,  0,1,\n             s,  0,  s,  0,  1,  0,  1,1,\n\n             s,  0, -s,  0,  1,  0,  1,0,\n            -s,  0, -s,  0,  1,  0,  0,0,\n             s,  0,  s,  0,  1,  0,  1,1,\n        ]\n\n        @uploadList vertices\n\n    setPointersForShader: (shader) ->\n        @gl.bindBuffer @gl.ARRAY_BUFFER, @buffer\n        @setPointer shader, 'position', 3, 0, 8\n        @setPointer shader, 'normal', 3, 3, 8\n        @setPointer shader, 'texcoord', 2, 6, 8\n\n        return @\n"
  },
  {
    "path": "lib/webgl/plane.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Plane,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Plane = (function(_super) {\n\n  __extends(Plane, _super);\n\n  Plane.prototype.attribs = ['position', 'normal', 'texcoord'];\n\n  function Plane(gl, s) {\n    var vertices;\n    this.gl = gl;\n    if (s == null) {\n      s = 1;\n    }\n    Plane.__super__.constructor.call(this);\n    this.size = 6;\n    vertices = [-s, 0, -s, 0, 1, 0, 0, 0, -s, 0, s, 0, 1, 0, 0, 1, s, 0, s, 0, 1, 0, 1, 1, s, 0, -s, 0, 1, 0, 1, 0, -s, 0, -s, 0, 1, 0, 0, 0, s, 0, s, 0, 1, 0, 1, 1];\n    this.uploadList(vertices);\n  }\n\n  Plane.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'normal', 3, 3, 8);\n    this.setPointer(shader, 'texcoord', 2, 6, 8);\n    return this;\n  };\n\n  return Plane;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/quad.coffee",
    "content": "return class Quad extends require('drawable')\n    attribs: ['position']\n    pointers: [\n        {name: 'position', size: 2, offset: 0, stride: 2},\n    ]\n\n    constructor: (@gl) ->\n        super()\n        @size = 6\n\n        vertices = [\n            -1, -1,  1, -1,  1, 1,\n            -1, -1,  1, 1,  -1, 1,\n        ]\n\n        @uploadList vertices\n"
  },
  {
    "path": "lib/webgl/quad.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Quad,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Quad = (function(_super) {\n\n  __extends(Quad, _super);\n\n  Quad.prototype.attribs = ['position'];\n\n  Quad.prototype.pointers = [\n    {\n      name: 'position',\n      size: 2,\n      offset: 0,\n      stride: 2\n    }\n  ];\n\n  function Quad(gl) {\n    var vertices;\n    this.gl = gl;\n    Quad.__super__.constructor.call(this);\n    this.size = 6;\n    vertices = [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1];\n    this.uploadList(vertices);\n  }\n\n  return Quad;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/shader.coffee",
    "content": "directives = [\n    '#ifdef GL_FRAGMENT_PRECISION_HIGH',\n    'precision highp int;',\n    'precision highp float;',\n    '#else',\n    'precision mediump int;',\n    'precision mediump float;',\n    '#endif',\n]\n\nin_use = null\n\nreturn class Shader\n    @lastError = ''\n\n    @splitLines = (path, source) ->\n        result = []\n        for line, i in source.split '\\n'\n            result.push\n                line: i\n                text: line\n                path: path\n        return result\n\n    @error = 'ShaderError'\n\n    constructor: (@gl, @path, source) ->\n        dirname = @path.split '/'\n        dirname.pop()\n        @dirname = dirname.join '/'\n\n        @program    = @gl.createProgram()\n        @vs         = @gl.createShader gl.VERTEX_SHADER\n        @fs         = @gl.createShader gl.FRAGMENT_SHADER\n\n        @gl.attachShader @program, @vs\n        @gl.attachShader @program, @fs\n\n        @link source\n\n    preprocess: (source) ->\n        lines = source.split '\\n'\n        shaders = {'global': [], 'fragment': [], 'vertex': []}\n        type = 'global'\n        for line, i in lines\n            match = line.match /^(\\w+):$/\n            if match\n                type = match[1]\n            else\n                shaders[type].push\n                    line: i\n                    text: line\n                    path: @path\n\n        global = @resolveLines(shaders.global)\n        shaders.fragment = global.concat(@resolveLines(shaders.fragment))\n        shaders.vertex = global.concat(@resolveLines(shaders.vertex))\n        return shaders\n\n    resolveLines: (stage) ->\n        result = []\n        for line in stage\n            match = line.text.match /^\\s+#require (\\S+)\\s*$/\n            if match\n                path = \"#{match[1]}.shaderlib\"\n                abspath = loader.resolvePath(@dirname, path)\n                lib = get abspath\n                for line in lib\n                    result.push line\n            else\n                result.push line\n        return result\n\n    concat: (stage) ->\n        result = ''\n        for line in directives\n            result += line + '\\n'\n        result += '#line 0\\n'\n        for line in stage\n            result += line.text + '\\n'\n        return result\n\n    link: (source) ->\n        shaders = @preprocess source\n        @compile @vs, shaders.vertex\n        @compile @fs, shaders.fragment\n        @gl.linkProgram @program\n\n        if not @gl.getProgramParameter @program, @gl.LINK_STATUS\n            error = \"Shader Link Error for file: #{@path}:\\n#{@gl.getProgramInfoLog(@program)}\"\n            console.error error\n            Shader.lastError = error\n            throw Shader.error\n\n        @attrib_cache = {}\n        @uniform_cache = {}\n        @value_cache = {}\n            \n    compile: (shader, lines) ->\n        source = @concat lines\n        @gl.shaderSource shader, source\n        @gl.compileShader shader\n\n        if not @gl.getShaderParameter shader, @gl.COMPILE_STATUS\n            error = @gl.getShaderInfoLog(shader)\n            group = \"Shader Compile Error for file: #{@path}\"\n            translated = @translateError(error, lines)\n            text = group + '\\n' + translated\n            Shader.lastError = text\n\n            console.group group\n            console.warn translated\n            console.groupEnd()\n\n            throw Shader.error\n        return\n\n    translateError: (error, sourcelines) ->\n        result = []\n        for line, i in error.split('\\n')\n            match = line.match /ERROR: \\d+:(\\d+): (.*)/\n            if match\n                lineno = parseFloat(match[1])\n                message = match[2]\n                sourceline = sourcelines[lineno-1]\n                result.push \"ERROR: Line #{sourceline.line+1}: File #{sourceline.path}: #{message} SOURCE: #{sourceline.text}\"\n            else\n                result.push line\n        return result.join('\\n')\n\n    attribLoc: (name) ->\n        location = @attrib_cache[name]\n        if location is undefined\n            location = @attrib_cache[name] = @gl.getAttribLocation @program, name\n        @gl.enableVertexAttribArray location if location >= 0\n        return location\n\n    use: ->\n        if @ != in_use\n            in_use = @\n            @gl.useProgram @program\n        return @\n    \n    unbind: ->\n        if in_use\n            in_use = null\n            @gl.useProgram null\n        return @\n\n    loc: (name) ->\n        location = @uniform_cache[name]\n        if location is undefined\n            location = @uniform_cache[name] = @gl.getUniformLocation @program, name\n        return location\n\n    i: (name, value) ->\n        cached = @value_cache[name]\n        if cached != value\n            @value_cache[name] = value\n            loc = @loc name\n            @gl.uniform1i loc, value if loc\n        return @\n\n    f: (name, value) ->\n        cached = @value_cache[name]\n        if cached != value\n            @value_cache[name] = value\n            loc = @loc name\n            @gl.uniform1f loc, value if loc\n        return @\n\n    fv: (name, values) ->\n        loc = @loc name\n        @gl.uniform1fv loc, values if loc\n        return @\n    \n    val2: (name, a, b) ->\n        cached = @value_cache[name]\n        if cached\n            if cached.a != a or cached.b != b\n                cached.a = a; cached.b = b\n                loc = @loc name\n                @gl.uniform2f loc, a, b if loc\n        else\n            @value_cache[name] = {a:a, b:b}\n            loc = @loc name\n            @gl.uniform2f loc, a, b if loc\n        return @\n    \n    val3: (name, a, b, c) ->\n        cached = @value_cache[name]\n        if cached\n            if cached.a != a or cached.b != b or cached.c != c\n                cached.a = a; cached.b = b; cached.c = c\n                loc = @loc name\n                @gl.uniform3f loc, a, b, c if loc\n        else\n            @value_cache[name] = {a:a, b:b, c:c}\n            loc = @loc name\n            @gl.uniform3f loc, a, b, c if loc\n        return @\n    \n    vec2: (name, value) ->\n        loc = @loc name\n        @gl.uniform2fv loc, value if loc\n        return @\n    \n    vec3: (name, value) ->\n        loc = @loc name\n        @gl.uniform3fv loc, value if loc\n        return @\n\n    val4: (name, a, b, c, d) ->\n        loc = @loc name\n        @gl.uniform4f loc, a, b, c, d if loc\n        return @\n    \n    vec4: (name, a, b, c, e) ->\n        loc = @loc name\n        @gl.uniform2f loc, a, b, c, e if loc\n        return @\n\n    mat4: (name, value) ->\n        loc = @loc name\n        if loc\n            if value instanceof Mat4\n                @gl.uniformMatrix4fv loc, @gl.FALSE, value.data\n            else\n                @gl.uniformMatrix4fv loc, @gl.FALSE, value\n        return @\n\n    mat3: (name, value) ->\n        loc = @loc name\n        @gl.uniformMatrix3fv loc, @gl.FALSE, value.data if loc\n        return @\n\n    draw: (drawable) ->\n        drawable\n            .setPointersForShader(@)\n            .draw()\n            .disableAttribs(@)\n        return @\n"
  },
  {
    "path": "lib/webgl/shader.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Shader, directives, in_use;\n\ndirectives = ['#ifdef GL_FRAGMENT_PRECISION_HIGH', 'precision highp int;', 'precision highp float;', '#else', 'precision mediump int;', 'precision mediump float;', '#endif'];\n\nin_use = null;\n\nreturn Shader = (function() {\n\n  Shader.lastError = '';\n\n  Shader.splitLines = function(path, source) {\n    var i, line, result, _i, _len, _ref;\n    result = [];\n    _ref = source.split('\\n');\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      line = _ref[i];\n      result.push({\n        line: i,\n        text: line,\n        path: path\n      });\n    }\n    return result;\n  };\n\n  Shader.error = 'ShaderError';\n\n  function Shader(gl, path, source) {\n    var dirname;\n    this.gl = gl;\n    this.path = path;\n    dirname = this.path.split('/');\n    dirname.pop();\n    this.dirname = dirname.join('/');\n    this.program = this.gl.createProgram();\n    this.vs = this.gl.createShader(gl.VERTEX_SHADER);\n    this.fs = this.gl.createShader(gl.FRAGMENT_SHADER);\n    this.gl.attachShader(this.program, this.vs);\n    this.gl.attachShader(this.program, this.fs);\n    this.link(source);\n  }\n\n  Shader.prototype.preprocess = function(source) {\n    var global, i, line, lines, match, shaders, type, _i, _len;\n    lines = source.split('\\n');\n    shaders = {\n      'global': [],\n      'fragment': [],\n      'vertex': []\n    };\n    type = 'global';\n    for (i = _i = 0, _len = lines.length; _i < _len; i = ++_i) {\n      line = lines[i];\n      match = line.match(/^(\\w+):$/);\n      if (match) {\n        type = match[1];\n      } else {\n        shaders[type].push({\n          line: i,\n          text: line,\n          path: this.path\n        });\n      }\n    }\n    global = this.resolveLines(shaders.global);\n    shaders.fragment = global.concat(this.resolveLines(shaders.fragment));\n    shaders.vertex = global.concat(this.resolveLines(shaders.vertex));\n    return shaders;\n  };\n\n  Shader.prototype.resolveLines = function(stage) {\n    var abspath, lib, line, match, path, result, _i, _j, _len, _len1;\n    result = [];\n    for (_i = 0, _len = stage.length; _i < _len; _i++) {\n      line = stage[_i];\n      match = line.text.match(/^\\s+#require (\\S+)\\s*$/);\n      if (match) {\n        path = \"\" + match[1] + \".shaderlib\";\n        abspath = loader.resolvePath(this.dirname, path);\n        lib = get(abspath);\n        for (_j = 0, _len1 = lib.length; _j < _len1; _j++) {\n          line = lib[_j];\n          result.push(line);\n        }\n      } else {\n        result.push(line);\n      }\n    }\n    return result;\n  };\n\n  Shader.prototype.concat = function(stage) {\n    var line, result, _i, _j, _len, _len1;\n    result = '';\n    for (_i = 0, _len = directives.length; _i < _len; _i++) {\n      line = directives[_i];\n      result += line + '\\n';\n    }\n    result += '#line 0\\n';\n    for (_j = 0, _len1 = stage.length; _j < _len1; _j++) {\n      line = stage[_j];\n      result += line.text + '\\n';\n    }\n    return result;\n  };\n\n  Shader.prototype.link = function(source) {\n    var error, shaders;\n    shaders = this.preprocess(source);\n    this.compile(this.vs, shaders.vertex);\n    this.compile(this.fs, shaders.fragment);\n    this.gl.linkProgram(this.program);\n    if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n      error = \"Shader Link Error for file: \" + this.path + \":\\n\" + (this.gl.getProgramInfoLog(this.program));\n      console.error(error);\n      Shader.lastError = error;\n      throw Shader.error;\n    }\n    this.attrib_cache = {};\n    this.uniform_cache = {};\n    return this.value_cache = {};\n  };\n\n  Shader.prototype.compile = function(shader, lines) {\n    var error, group, source, text, translated;\n    source = this.concat(lines);\n    this.gl.shaderSource(shader, source);\n    this.gl.compileShader(shader);\n    if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n      error = this.gl.getShaderInfoLog(shader);\n      group = \"Shader Compile Error for file: \" + this.path;\n      translated = this.translateError(error, lines);\n      text = group + '\\n' + translated;\n      Shader.lastError = text;\n      console.group(group);\n      console.warn(translated);\n      console.groupEnd();\n      throw Shader.error;\n    }\n  };\n\n  Shader.prototype.translateError = function(error, sourcelines) {\n    var i, line, lineno, match, message, result, sourceline, _i, _len, _ref;\n    result = [];\n    _ref = error.split('\\n');\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      line = _ref[i];\n      match = line.match(/ERROR: \\d+:(\\d+): (.*)/);\n      if (match) {\n        lineno = parseFloat(match[1]);\n        message = match[2];\n        sourceline = sourcelines[lineno - 1];\n        result.push(\"ERROR: Line \" + (sourceline.line + 1) + \": File \" + sourceline.path + \": \" + message + \" SOURCE: \" + sourceline.text);\n      } else {\n        result.push(line);\n      }\n    }\n    return result.join('\\n');\n  };\n\n  Shader.prototype.attribLoc = function(name) {\n    var location;\n    location = this.attrib_cache[name];\n    if (location === void 0) {\n      location = this.attrib_cache[name] = this.gl.getAttribLocation(this.program, name);\n    }\n    if (location >= 0) {\n      this.gl.enableVertexAttribArray(location);\n    }\n    return location;\n  };\n\n  Shader.prototype.use = function() {\n    if (this !== in_use) {\n      in_use = this;\n      this.gl.useProgram(this.program);\n    }\n    return this;\n  };\n\n  Shader.prototype.unbind = function() {\n    if (in_use) {\n      in_use = null;\n      this.gl.useProgram(null);\n    }\n    return this;\n  };\n\n  Shader.prototype.loc = function(name) {\n    var location;\n    location = this.uniform_cache[name];\n    if (location === void 0) {\n      location = this.uniform_cache[name] = this.gl.getUniformLocation(this.program, name);\n    }\n    return location;\n  };\n\n  Shader.prototype.i = function(name, value) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached !== value) {\n      this.value_cache[name] = value;\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform1i(loc, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.f = function(name, value) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached !== value) {\n      this.value_cache[name] = value;\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform1f(loc, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.fv = function(name, values) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform1fv(loc, values);\n    }\n    return this;\n  };\n\n  Shader.prototype.val2 = function(name, a, b) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached) {\n      if (cached.a !== a || cached.b !== b) {\n        cached.a = a;\n        cached.b = b;\n        loc = this.loc(name);\n        if (loc) {\n          this.gl.uniform2f(loc, a, b);\n        }\n      }\n    } else {\n      this.value_cache[name] = {\n        a: a,\n        b: b\n      };\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform2f(loc, a, b);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.val3 = function(name, a, b, c) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached) {\n      if (cached.a !== a || cached.b !== b || cached.c !== c) {\n        cached.a = a;\n        cached.b = b;\n        cached.c = c;\n        loc = this.loc(name);\n        if (loc) {\n          this.gl.uniform3f(loc, a, b, c);\n        }\n      }\n    } else {\n      this.value_cache[name] = {\n        a: a,\n        b: b,\n        c: c\n      };\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform3f(loc, a, b, c);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.vec2 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform2fv(loc, value);\n    }\n    return this;\n  };\n\n  Shader.prototype.vec3 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform3fv(loc, value);\n    }\n    return this;\n  };\n\n  Shader.prototype.val4 = function(name, a, b, c, d) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform4f(loc, a, b, c, d);\n    }\n    return this;\n  };\n\n  Shader.prototype.vec4 = function(name, a, b, c, e) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform2f(loc, a, b, c, e);\n    }\n    return this;\n  };\n\n  Shader.prototype.mat4 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      if (value instanceof Mat4) {\n        this.gl.uniformMatrix4fv(loc, this.gl.FALSE, value.data);\n      } else {\n        this.gl.uniformMatrix4fv(loc, this.gl.FALSE, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.mat3 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniformMatrix3fv(loc, this.gl.FALSE, value.data);\n    }\n    return this;\n  };\n\n  Shader.prototype.draw = function(drawable) {\n    drawable.setPointersForShader(this).draw().disableAttribs(this);\n    return this;\n  };\n\n  return Shader;\n\n})();\n"
  },
  {
    "path": "lib/webgl/sphere.coffee",
    "content": "phi = (1+Math.sqrt(5))/2\n        \nmidp = (v1, v2) ->\n    x1 = v1[0]\n    y1 = v1[1]\n    z1 = v1[2]\n  \n    x2 = v2[0]\n    y2 = v2[1]\n    z2 = v2[2]\n    \n    x3 = (x1+x2)/2\n    y3 = (y1+y2)/2\n    z3 = (z1+z2)/2\n\n    return [x3, y3, z3]\n    \nnormalize = (faces, r) ->\n    r ?= 1\n    result = []\n    for face in faces\n        new_face = []\n        result.push new_face\n        for vertex in face\n            x = vertex[0]\n            y = vertex[1]\n            z = vertex[2]\n            l = Math.sqrt(x*x + y*y + z*z)\n            new_face.push [(r*x)/l, (r*y)/l, (r*z)/l]\n    return result\n    \nsubdivide = (faces) ->\n    result = []\n    for face in faces\n        v0 = face[0]\n        v1 = face[1]\n        v2 = face[2]\n\n        va = midp v0, v1\n        vb = midp v1, v2\n        vc = midp v2, v0\n\n        result.push(\n            [v0, va, vc],\n            [va, v1, vb],\n            [vc, vb, v2],\n            [va, vb, vc],\n        )\n\n    return result\n    \nv1  = [   1,  phi,    0]\nv2  = [  -1,  phi,    0]\nv3  = [   0,    1,  phi]\nv4  = [   0,    1, -phi]\nv5  = [ phi,    0,    1]\nv6  = [-phi,    0,    1]\nv7  = [-phi,    0,   -1]\nv8  = [ phi,    0,   -1]\nv9  = [   0,   -1,  phi]\nv10 = [   0,   -1, -phi]\nv11 = [  -1, -phi,    0]\nv12 = [   1, -phi,    0]\n\nfaces = [\n  [ v1,  v2,  v3],\n  [ v2,  v1,  v4],\n  [ v1,  v3,  v5],\n  [ v2,  v6,  v3],\n  [ v2,  v7,  v6],\n  [ v2,  v4,  v7],\n  [ v1,  v5,  v8],\n  [ v1,  v8,  v4],\n  [ v9,  v3,  v6],\n  [ v3,  v9,  v5],\n  [ v4, v10,  v7],\n  [ v4,  v8, v10],\n  [ v6,  v7, v11],\n  [ v6, v11,  v9],\n  [ v7, v10, v11],\n  [ v5, v12,  v8],\n  [v12,  v5,  v9],\n  [v12, v10,  v8],\n  [v11, v12,  v9],\n  [v12, v11, v10]\n]\n\nicosahedron = normalize(faces)\n\nvertexlist = (faces) ->\n    vertices = []\n    for face in faces\n        for vertex in face\n            x = vertex[0]\n            y = vertex[1]\n            z = vertex[2]\n            vertices.push x, y, z\n    return vertices\n\nreturn class Sphere extends require('drawable')\n    attribs: ['position']\n    pointers: [\n        {name: 'position',      size: 3, offset: 0, stride: 3},\n    ]\n\n    @makeVertices = (radius=1, subdivisions=3) ->\n        template = icosahedron\n        for i in [0...subdivisions]\n            template = subdivide template\n            template = normalize template\n        faces = normalize template, radius\n        vertices = vertexlist faces\n        return vertices\n\n    constructor: (@gl, radius=1, subdivisions=3) ->\n        super()\n        vertices = Sphere.makeVertices radius, subdivisions\n        @size = vertices.length/3\n        @uploadList vertices\n"
  },
  {
    "path": "lib/webgl/sphere.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Sphere, faces, icosahedron, midp, normalize, phi, subdivide, v1, v10, v11, v12, v2, v3, v4, v5, v6, v7, v8, v9, vertexlist,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nphi = (1 + Math.sqrt(5)) / 2;\n\nmidp = function(v1, v2) {\n  var x1, x2, x3, y1, y2, y3, z1, z2, z3;\n  x1 = v1[0];\n  y1 = v1[1];\n  z1 = v1[2];\n  x2 = v2[0];\n  y2 = v2[1];\n  z2 = v2[2];\n  x3 = (x1 + x2) / 2;\n  y3 = (y1 + y2) / 2;\n  z3 = (z1 + z2) / 2;\n  return [x3, y3, z3];\n};\n\nnormalize = function(faces, r) {\n  var face, l, new_face, result, vertex, x, y, z, _i, _j, _len, _len1;\n  if (r == null) {\n    r = 1;\n  }\n  result = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    new_face = [];\n    result.push(new_face);\n    for (_j = 0, _len1 = face.length; _j < _len1; _j++) {\n      vertex = face[_j];\n      x = vertex[0];\n      y = vertex[1];\n      z = vertex[2];\n      l = Math.sqrt(x * x + y * y + z * z);\n      new_face.push([(r * x) / l, (r * y) / l, (r * z) / l]);\n    }\n  }\n  return result;\n};\n\nsubdivide = function(faces) {\n  var face, result, v0, v1, v2, va, vb, vc, _i, _len;\n  result = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    v0 = face[0];\n    v1 = face[1];\n    v2 = face[2];\n    va = midp(v0, v1);\n    vb = midp(v1, v2);\n    vc = midp(v2, v0);\n    result.push([v0, va, vc], [va, v1, vb], [vc, vb, v2], [va, vb, vc]);\n  }\n  return result;\n};\n\nv1 = [1, phi, 0];\n\nv2 = [-1, phi, 0];\n\nv3 = [0, 1, phi];\n\nv4 = [0, 1, -phi];\n\nv5 = [phi, 0, 1];\n\nv6 = [-phi, 0, 1];\n\nv7 = [-phi, 0, -1];\n\nv8 = [phi, 0, -1];\n\nv9 = [0, -1, phi];\n\nv10 = [0, -1, -phi];\n\nv11 = [-1, -phi, 0];\n\nv12 = [1, -phi, 0];\n\nfaces = [[v1, v2, v3], [v2, v1, v4], [v1, v3, v5], [v2, v6, v3], [v2, v7, v6], [v2, v4, v7], [v1, v5, v8], [v1, v8, v4], [v9, v3, v6], [v3, v9, v5], [v4, v10, v7], [v4, v8, v10], [v6, v7, v11], [v6, v11, v9], [v7, v10, v11], [v5, v12, v8], [v12, v5, v9], [v12, v10, v8], [v11, v12, v9], [v12, v11, v10]];\n\nicosahedron = normalize(faces);\n\nvertexlist = function(faces) {\n  var face, vertex, vertices, x, y, z, _i, _j, _len, _len1;\n  vertices = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    for (_j = 0, _len1 = face.length; _j < _len1; _j++) {\n      vertex = face[_j];\n      x = vertex[0];\n      y = vertex[1];\n      z = vertex[2];\n      vertices.push(x, y, z);\n    }\n  }\n  return vertices;\n};\n\nreturn Sphere = (function(_super) {\n\n  __extends(Sphere, _super);\n\n  Sphere.prototype.attribs = ['position'];\n\n  Sphere.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 3\n    }\n  ];\n\n  Sphere.makeVertices = function(radius, subdivisions) {\n    var i, template, vertices, _i;\n    if (radius == null) {\n      radius = 1;\n    }\n    if (subdivisions == null) {\n      subdivisions = 3;\n    }\n    template = icosahedron;\n    for (i = _i = 0; 0 <= subdivisions ? _i < subdivisions : _i > subdivisions; i = 0 <= subdivisions ? ++_i : --_i) {\n      template = subdivide(template);\n      template = normalize(template);\n    }\n    faces = normalize(template, radius);\n    vertices = vertexlist(faces);\n    return vertices;\n  };\n\n  function Sphere(gl, radius, subdivisions) {\n    var vertices;\n    this.gl = gl;\n    if (radius == null) {\n      radius = 1;\n    }\n    if (subdivisions == null) {\n      subdivisions = 3;\n    }\n    Sphere.__super__.constructor.call(this);\n    vertices = Sphere.makeVertices(radius, subdivisions);\n    this.size = vertices.length / 3;\n    this.uploadList(vertices);\n  }\n\n  return Sphere;\n\n})(require('drawable'));\n"
  },
  {
    "path": "lib/webgl/texture.coffee",
    "content": "{Framebuffer} = require 'framebuffer'\n\nclass Texture\n    bound = []\n    ids = 0\n\n    constructor: ->\n        @handle = @gl.createTexture()\n        @id = ids++\n        @unit = null\n\n    bind: (unit=0) ->\n        @unit = unit\n        if bound[unit] != @id\n            @gl.activeTexture @gl.TEXTURE0+unit\n            @gl.bindTexture @target, @handle\n            bound[unit] = @id\n        return @\n    \n    unbind: (unit=@unit) ->\n        if unit and bound[unit] == @id\n            @gl.activeTexture @gl.TEXTURE0+unit\n            @gl.bindTexture @target, null\n            bound[unit] = null\n        return @\n    \n    mipmap: ->\n        @gl.texParameteri @target, @gl.TEXTURE_MAG_FILTER, @gl.LINEAR\n        @gl.texParameteri @target, @gl.TEXTURE_MIN_FILTER, @gl.LINEAR_MIPMAP_LINEAR\n        @gl.generateMipmap @target\n        return @\n    \n    mipmapNearest: ->\n        @gl.texParameteri @target, @gl.TEXTURE_MAG_FILTER, @gl.NEAREST\n        @gl.texParameteri @target, @gl.TEXTURE_MIN_FILTER, @gl.LINEAR_MIPMAP_LINEAR\n        @gl.generateMipmap @target\n        return @\n\n    linear: ->\n        @gl.texParameteri @target, @gl.TEXTURE_MAG_FILTER, @gl.LINEAR\n        @gl.texParameteri @target, @gl.TEXTURE_MIN_FILTER, @gl.LINEAR\n        return @\n    \n    nearest: ->\n        @gl.texParameteri @target, @gl.TEXTURE_MAG_FILTER, @gl.NEAREST\n        @gl.texParameteri @target, @gl.TEXTURE_MIN_FILTER, @gl.NEAREST\n        return @\n    \n    clampToEdge: ->\n        @gl.texParameteri @target, @gl.TEXTURE_WRAP_S, @gl.CLAMP_TO_EDGE\n        @gl.texParameteri @target, @gl.TEXTURE_WRAP_T, @gl.CLAMP_TO_EDGE\n        return @\n    \n    repeat: ->\n        @gl.texParameteri @target, @gl.TEXTURE_WRAP_S, @gl.REPEAT\n        @gl.texParameteri @target, @gl.TEXTURE_WRAP_T, @gl.REPEAT\n        return @\n            \n    anisotropy: ->\n        ext = @gl.getExtension 'WEBKIT_EXT_texture_filter_anisotropic'\n        if ext\n            max = @gl.getParameter ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT\n            @gl.texParameterf @target, ext.TEXTURE_MAX_ANISOTROPY_EXT, max\n        return @\n\nexports.Texture2D = class Texture2D extends Texture\n    constructor: (@gl, {@channels, @format, @type}={}) ->\n        super()\n        @channels ?= @gl.RGBA\n        @format ?= @gl.RGBA\n        @type ?= @gl.UNSIGNED_BYTE\n        @target = @gl.TEXTURE_2D\n\n    upload: (image) ->\n        @uploadImage image\n        return @\n\n    uploadImage: (image) ->\n        @width = image.width\n        @height = image.height\n        @gl.texImage2D @target, 0, @channels, @format, @type, image\n        return @\n\n    uploadData: (data, @width, @height) ->\n        @gl.texImage2D @target, 0, @channels, width, height, 0, @format, @type, data\n        return @\n\n    setSize: (@width, @height) ->\n        @gl.texImage2D @target, 0, @channels, width, height, 0, @format, @type, null\n        return @\n\n    read: (dst=new Uint8Array(@width*@height*4)) ->\n        if @fbo\n            @fbo.bind()\n        else\n            @fbo = new Framebuffer(@gl).bind().color(@)\n        \n        @gl.readPixels 0, 0, @width, @height, @gl.RGBA, @gl.UNSIGNED_BYTE, dst\n        @fbo.unbind()\n\n        return dst\n\n    toPNG: ->\n        canvas = document.createElement 'canvas'\n        canvas.height = @height\n        canvas.width = @width\n        ctx = canvas.getContext '2d'\n        imgdata = ctx.createImageData @width, @height\n        imgdata.data.set @read(), 0\n        ctx.putImageData imgdata, 0, 0\n        url = canvas.toDataURL 'image/png'\n        data = atob(url.split(',')[1])\n        result = new Uint8Array(data.length)\n        for i in [0...data.length]\n            result[i] = data.charCodeAt i\n        return result\n        \nexports.Cubemap = class Cubemap extends Texture\n    constructor: (@gl) ->\n        super()\n        @target = @gl.TEXTURE_CUBE_MAP\n\n        @up = @gl.TEXTURE_CUBE_MAP_POSITIVE_Y\n        @down = @gl.TEXTURE_CUBE_MAP_NEGATIVE_Y\n        @right = @gl.TEXTURE_CUBE_MAP_POSITIVE_X\n        @left = @gl.TEXTURE_CUBE_MAP_NEGATIVE_X\n        @back = @gl.TEXTURE_CUBE_MAP_NEGATIVE_Z\n        @front = @gl.TEXTURE_CUBE_MAP_POSITIVE_Z\n\n    uploadSide: (name, image) ->\n        @gl.texImage2D @gl['TEXTURE_CUBE_MAP_' + name], 0, @gl.RGBA, @gl.RGBA, @gl.UNSIGNED_BYTE, image\n\n    upload: (folder, ext='jpg') ->\n        @uploadSide 'POSITIVE_Y', folder.get \"up.#{ext}\"\n        @uploadSide 'NEGATIVE_Y', folder.get \"down.#{ext}\"\n        @uploadSide 'POSITIVE_X', folder.get \"right.#{ext}\"\n        @uploadSide 'NEGATIVE_X', folder.get \"left.#{ext}\"\n        @uploadSide 'POSITIVE_Z', folder.get \"front.#{ext}\"\n        @uploadSide 'NEGATIVE_Z', folder.get \"back.#{ext}\"\n        return @\n\n    setSize: (@size) ->\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        @gl.texImage2D @gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, @gl.RGBA, @size, @size, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, null\n        return @\n"
  },
  {
    "path": "lib/webgl/texture.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Cubemap, Framebuffer, Texture, Texture2D,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nFramebuffer = require('framebuffer').Framebuffer;\n\nTexture = (function() {\n  var bound, ids;\n\n  bound = [];\n\n  ids = 0;\n\n  function Texture() {\n    this.handle = this.gl.createTexture();\n    this.id = ids++;\n    this.unit = null;\n  }\n\n  Texture.prototype.bind = function(unit) {\n    if (unit == null) {\n      unit = 0;\n    }\n    this.unit = unit;\n    if (bound[unit] !== this.id) {\n      this.gl.activeTexture(this.gl.TEXTURE0 + unit);\n      this.gl.bindTexture(this.target, this.handle);\n      bound[unit] = this.id;\n    }\n    return this;\n  };\n\n  Texture.prototype.unbind = function(unit) {\n    if (unit == null) {\n      unit = this.unit;\n    }\n    if (unit && bound[unit] === this.id) {\n      this.gl.activeTexture(this.gl.TEXTURE0 + unit);\n      this.gl.bindTexture(this.target, null);\n      bound[unit] = null;\n    }\n    return this;\n  };\n\n  Texture.prototype.mipmap = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n    this.gl.generateMipmap(this.target);\n    return this;\n  };\n\n  Texture.prototype.mipmapNearest = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n    this.gl.generateMipmap(this.target);\n    return this;\n  };\n\n  Texture.prototype.linear = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n    return this;\n  };\n\n  Texture.prototype.nearest = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);\n    return this;\n  };\n\n  Texture.prototype.clampToEdge = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n    return this;\n  };\n\n  Texture.prototype.repeat = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT);\n    return this;\n  };\n\n  Texture.prototype.anisotropy = function() {\n    var ext, max;\n    ext = this.gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');\n    if (ext) {\n      max = this.gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);\n      this.gl.texParameterf(this.target, ext.TEXTURE_MAX_ANISOTROPY_EXT, max);\n    }\n    return this;\n  };\n\n  return Texture;\n\n})();\n\nexports.Texture2D = Texture2D = (function(_super) {\n\n  __extends(Texture2D, _super);\n\n  function Texture2D(gl, _arg) {\n    var _ref, _ref1, _ref2, _ref3;\n    this.gl = gl;\n    _ref = _arg != null ? _arg : {}, this.channels = _ref.channels, this.format = _ref.format, this.type = _ref.type;\n    Texture2D.__super__.constructor.call(this);\n    if ((_ref1 = this.channels) == null) {\n      this.channels = this.gl.RGBA;\n    }\n    if ((_ref2 = this.format) == null) {\n      this.format = this.gl.RGBA;\n    }\n    if ((_ref3 = this.type) == null) {\n      this.type = this.gl.UNSIGNED_BYTE;\n    }\n    this.target = this.gl.TEXTURE_2D;\n  }\n\n  Texture2D.prototype.upload = function(image) {\n    this.uploadImage(image);\n    return this;\n  };\n\n  Texture2D.prototype.uploadImage = function(image) {\n    this.width = image.width;\n    this.height = image.height;\n    this.gl.texImage2D(this.target, 0, this.channels, this.format, this.type, image);\n    return this;\n  };\n\n  Texture2D.prototype.uploadData = function(data, width, height) {\n    this.width = width;\n    this.height = height;\n    this.gl.texImage2D(this.target, 0, this.channels, width, height, 0, this.format, this.type, data);\n    return this;\n  };\n\n  Texture2D.prototype.setSize = function(width, height) {\n    this.width = width;\n    this.height = height;\n    this.gl.texImage2D(this.target, 0, this.channels, width, height, 0, this.format, this.type, null);\n    return this;\n  };\n\n  Texture2D.prototype.read = function(dst) {\n    if (dst == null) {\n      dst = new Uint8Array(this.width * this.height * 4);\n    }\n    if (this.fbo) {\n      this.fbo.bind();\n    } else {\n      this.fbo = new Framebuffer(this.gl).bind().color(this);\n    }\n    this.gl.readPixels(0, 0, this.width, this.height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, dst);\n    this.fbo.unbind();\n    return dst;\n  };\n\n  Texture2D.prototype.toPNG = function() {\n    var canvas, ctx, data, i, imgdata, result, url, _i, _ref;\n    canvas = document.createElement('canvas');\n    canvas.height = this.height;\n    canvas.width = this.width;\n    ctx = canvas.getContext('2d');\n    imgdata = ctx.createImageData(this.width, this.height);\n    imgdata.data.set(this.read(), 0);\n    ctx.putImageData(imgdata, 0, 0);\n    url = canvas.toDataURL('image/png');\n    data = atob(url.split(',')[1]);\n    result = new Uint8Array(data.length);\n    for (i = _i = 0, _ref = data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n      result[i] = data.charCodeAt(i);\n    }\n    return result;\n  };\n\n  return Texture2D;\n\n})(Texture);\n\nexports.Cubemap = Cubemap = (function(_super) {\n\n  __extends(Cubemap, _super);\n\n  function Cubemap(gl) {\n    this.gl = gl;\n    Cubemap.__super__.constructor.call(this);\n    this.target = this.gl.TEXTURE_CUBE_MAP;\n    this.up = this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y;\n    this.down = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y;\n    this.right = this.gl.TEXTURE_CUBE_MAP_POSITIVE_X;\n    this.left = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X;\n    this.back = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z;\n    this.front = this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z;\n  }\n\n  Cubemap.prototype.uploadSide = function(name, image) {\n    return this.gl.texImage2D(this.gl['TEXTURE_CUBE_MAP_' + name], 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);\n  };\n\n  Cubemap.prototype.upload = function(folder, ext) {\n    if (ext == null) {\n      ext = 'jpg';\n    }\n    this.uploadSide('POSITIVE_Y', folder.get(\"up.\" + ext));\n    this.uploadSide('NEGATIVE_Y', folder.get(\"down.\" + ext));\n    this.uploadSide('POSITIVE_X', folder.get(\"right.\" + ext));\n    this.uploadSide('NEGATIVE_X', folder.get(\"left.\" + ext));\n    this.uploadSide('POSITIVE_Z', folder.get(\"front.\" + ext));\n    this.uploadSide('NEGATIVE_Z', folder.get(\"back.\" + ext));\n    return this;\n  };\n\n  Cubemap.prototype.setSize = function(size) {\n    this.size = size;\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    return this;\n  };\n\n  return Cubemap;\n\n})(Texture);\n"
  },
  {
    "path": "lib/webgl-nuke-vendor-prefix.coffee",
    "content": "if window.WebGLRenderingContext?\n    vendors = ['WEBKIT', 'MOZ', 'MS', 'O']\n    vendorRe = /^WEBKIT_(.*)|MOZ_(.*)|MS_(.*)|O_(.*)/\n\n    getExtension = WebGLRenderingContext.prototype.getExtension\n    WebGLRenderingContext.prototype.getExtension = (name) ->\n        match = name.match vendorRe\n        if match != null\n            name = match[1]\n\n        extobj = getExtension.call @, name\n        if extobj == null\n            for vendor in vendors\n                extobj = getExtension.call @, vendor + '_' + name\n                if extobj != null\n                    return extobj\n            return null\n        else\n            return extobj\n\n    getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions\n    WebGLRenderingContext.prototype.getSupportedExtensions = ->\n        supported = getSupportedExtensions.call @\n        result = []\n\n        for extension in supported\n            match = extension.match vendorRe\n            if match != null\n                extension = match[1]\n\n            if extension not in result\n                result.push extension\n\n        return result\n"
  },
  {
    "path": "lib/webgl-nuke-vendor-prefix.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar getExtension, getSupportedExtensions, vendorRe, vendors,\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\nif (window.WebGLRenderingContext != null) {\n  vendors = ['WEBKIT', 'MOZ', 'MS', 'O'];\n  vendorRe = /^WEBKIT_(.*)|MOZ_(.*)|MS_(.*)|O_(.*)/;\n  getExtension = WebGLRenderingContext.prototype.getExtension;\n  WebGLRenderingContext.prototype.getExtension = function(name) {\n    var extobj, match, vendor, _i, _len;\n    match = name.match(vendorRe);\n    if (match !== null) {\n      name = match[1];\n    }\n    extobj = getExtension.call(this, name);\n    if (extobj === null) {\n      for (_i = 0, _len = vendors.length; _i < _len; _i++) {\n        vendor = vendors[_i];\n        extobj = getExtension.call(this, vendor + '_' + name);\n        if (extobj !== null) {\n          return extobj;\n        }\n      }\n      return null;\n    } else {\n      return extobj;\n    }\n  };\n  getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;\n  WebGLRenderingContext.prototype.getSupportedExtensions = function() {\n    var extension, match, result, supported, _i, _len;\n    supported = getSupportedExtensions.call(this);\n    result = [];\n    for (_i = 0, _len = supported.length; _i < _len; _i++) {\n      extension = supported[_i];\n      match = extension.match(vendorRe);\n      if (match !== null) {\n        extension = match[1];\n      }\n      if (__indexOf.call(result, extension) < 0) {\n        result.push(extension);\n      }\n    }\n    return result;\n  };\n}\n"
  },
  {
    "path": "lib/webgl-texture-float-extension-shims.coffee",
    "content": "createSourceCanvas = ->\n    canvas = document.createElement 'canvas'\n    canvas.width = 2\n    canvas.height = 2\n    ctx = canvas.getContext '2d'\n    imageData = ctx.getImageData(0, 0, 2, 2)\n    imageData.data.set(new Uint8ClampedArray([\n        0,0,0,0,\n        255,255,255,255,\n        0,0,0,0,\n        255,255,255,255,\n    ]))\n    ctx.putImageData(imageData, 0, 0)\n    return canvas\n\ncreateSourceCanvas()\n\ncheckFloatLinear = (gl, sourceType) ->\n    ## drawing program ##\n    program = gl.createProgram()\n    vertexShader = gl.createShader(gl.VERTEX_SHADER)\n    gl.attachShader(program, vertexShader)\n    gl.shaderSource(vertexShader, '''\n        attribute vec2 position;\n        void main(){\n            gl_Position = vec4(position, 0.0, 1.0);\n        }\n    ''')\n\n    gl.compileShader(vertexShader)\n    if not gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)\n        throw gl.getShaderInfoLog(vertexShader)\n\n    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)\n    gl.attachShader(program, fragmentShader)\n    gl.shaderSource(fragmentShader, '''\n        uniform sampler2D source;\n        void main(){\n            gl_FragColor = texture2D(source, vec2(1.0, 1.0));\n        }\n    ''')\n    gl.compileShader(fragmentShader)\n    if not gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)\n        throw gl.getShaderInfoLog(fragmentShader)\n\n    gl.linkProgram(program)\n    if not gl.getProgramParameter(program, gl.LINK_STATUS)\n        throw gl.getProgramInfoLog(program)\n    \n    gl.useProgram(program)\n    \n    cleanup = ->\n        gl.deleteShader(fragmentShader)\n        gl.deleteShader(vertexShader)\n        gl.deleteProgram(program)\n        gl.deleteBuffer(buffer)\n        gl.deleteTexture(source)\n        gl.deleteTexture(target)\n        gl.deleteFramebuffer(framebuffer)\n\n        gl.bindBuffer(gl.ARRAY_BUFFER, null)\n        gl.useProgram(null)\n        gl.bindTexture(gl.TEXTURE_2D, null)\n        gl.bindFramebuffer(gl.FRAMEBUFFER, null)\n\n    ## target FBO ##\n    target = gl.createTexture()\n    gl.bindTexture(gl.TEXTURE_2D, target)\n    gl.texImage2D(\n        gl.TEXTURE_2D,\n        0,\n        gl.RGBA,\n        2, 2,\n        0,\n        gl.RGBA,\n        gl.UNSIGNED_BYTE,\n        null,\n    )\n\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n\n    framebuffer = gl.createFramebuffer()\n    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)\n    gl.framebufferTexture2D(\n        gl.FRAMEBUFFER,\n        gl.COLOR_ATTACHMENT0,\n        gl.TEXTURE_2D,\n        target,\n        0\n    )\n    \n    ## source texture ##\n    sourceCanvas = createSourceCanvas()\n    source = gl.createTexture()\n    gl.bindTexture(gl.TEXTURE_2D, source)\n    gl.texImage2D(\n        gl.TEXTURE_2D,\n        0,\n        gl.RGBA,\n        gl.RGBA,\n        sourceType,\n        sourceCanvas,\n    )\n\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)\n    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)\n               \n    ## create VBO ## \n    vertices = new Float32Array([\n         1,  1,\n        -1,  1,\n        -1, -1,\n\n         1,  1,\n        -1, -1,\n         1, -1,\n    ])\n    buffer = gl.createBuffer()\n    gl.bindBuffer(gl.ARRAY_BUFFER, buffer)\n    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)\n    positionLoc = gl.getAttribLocation(program, 'position')\n    sourceLoc = gl.getUniformLocation(program, 'source')\n    gl.enableVertexAttribArray(positionLoc)\n    gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0)\n    gl.uniform1i(sourceLoc, 0)\n    gl.drawArrays(gl.TRIANGLES, 0, 6)\n    \n    readBuffer = new Uint8Array(4*4)\n    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, readBuffer)\n   \n    result = Math.abs(readBuffer[0] - 127) < 10\n\n    cleanup()\n    return result\n\ncheckTexture = (gl, targetType) ->\n    target = gl.createTexture()\n    gl.bindTexture(gl.TEXTURE_2D, target)\n    gl.texImage2D(\n        gl.TEXTURE_2D,\n        0,\n        gl.RGBA,\n        2, 2,\n        0,\n        gl.RGBA,\n        targetType,\n        null,\n    )\n\n    if gl.getError() == 0\n        gl.deleteTexture(target)\n        return true\n    else\n        gl.deleteTexture(target)\n        return false\n\ncheckColorBuffer = (gl, targetType) ->\n    target = gl.createTexture()\n    gl.bindTexture(gl.TEXTURE_2D, target)\n    gl.texImage2D(\n        gl.TEXTURE_2D,\n        0,\n        gl.RGBA,\n        2, 2,\n        0,\n        gl.RGBA,\n        targetType,\n        null,\n    )\n    \n    framebuffer = gl.createFramebuffer()\n    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)\n    gl.framebufferTexture2D(\n        gl.FRAMEBUFFER,\n        gl.COLOR_ATTACHMENT0,\n        gl.TEXTURE_2D,\n        target,\n        0\n    )\n    \n    check = gl.checkFramebufferStatus(gl.FRAMEBUFFER)\n\n    gl.deleteTexture(target)\n    gl.deleteFramebuffer(framebuffer)\n    gl.bindTexture(gl.TEXTURE_2D, null)\n    gl.bindFramebuffer(gl.FRAMEBUFFER, null)\n\n    if check == gl.FRAMEBUFFER_COMPLETE\n        return true\n    else\n        return false\n\nshimExtensions = []\nshimLookup = {}\nunshimExtensions = []\n\ncheckSupport = ->\n    canvas = document.createElement 'canvas'\n    gl = null\n    try\n        gl = canvas.getContext 'experimental-webgl'\n        if(gl == null)\n            gl = canvas.getContext 'webgl'\n\n    if gl?\n        singleFloatExt = gl.getExtension 'OES_texture_float'\n        if singleFloatExt == null\n            if checkTexture gl, gl.FLOAT\n                singleFloatTexturing = true\n                shimExtensions.push 'OES_texture_float'\n                shimLookup.OES_texture_float = {shim:true}\n            else\n                singleFloatTexturing = false\n                unshimExtensions.push 'OES_texture_float'\n        else\n            if checkTexture gl, gl.FLOAT\n                singleFloatTexturing = true\n                shimExtensions.push 'OES_texture_float'\n            else\n                singleFloatTexturing = false\n                unshimExtensions.push 'OES_texture_float'\n\n        if singleFloatTexturing\n            extobj = gl.getExtension 'WEBGL_color_buffer_float'\n            if extobj == null\n                if checkColorBuffer gl, gl.FLOAT\n                    shimExtensions.push 'WEBGL_color_buffer_float'\n                    shimLookup.WEBGL_color_buffer_float = {\n                        shim: true\n                        RGBA32F_EXT: 0x8814\n                        RGB32F_EXT: 0x8815\n                        FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211\n                        UNSIGNED_NORMALIZED_EXT: 0x8C17\n                    }\n                else\n                    unshimExtensions.push 'WEBGL_color_buffer_float'\n            else\n                if checkColorBuffer gl, gl.FLOAT\n                    shimExtensions.push 'WEBGL_color_buffer_float'\n                else\n                    unshimExtensions.push 'WEBGL_color_buffer_float'\n\n            extobj = gl.getExtension 'OES_texture_float_linear'\n            if extobj == null\n                if checkFloatLinear gl, gl.FLOAT\n                    shimExtensions.push 'OES_texture_float_linear'\n                    shimLookup.OES_texture_float_linear = {shim:true}\n                else\n                    unshimExtensions.push 'OES_texture_float_linear'\n            else\n                if checkFloatLinear gl, gl.FLOAT\n                    shimExtensions.push 'OES_texture_float_linear'\n                else\n                    unshimExtensions.push 'OES_texture_float_linear'\n        \n        halfFloatExt = gl.getExtension 'OES_texture_half_float'\n        if halfFloatExt == null\n            if checkTexture(gl, 0x8D61)\n                halfFloatTexturing = true\n                shimExtensions.push 'OES_texture_half_float'\n                halfFloatExt = shimLookup.OES_texture_half_float = {\n                    HALF_FLOAT_OES: 0x8D61\n                    shim:true\n                }\n            else\n                halfFloatTexturing = false\n                unshimExtensions.push 'OES_texture_half_float'\n        else\n            if checkTexture(gl, halfFloatExt.HALF_FLOAT_OES)\n                halfFloatTexturing = true\n                shimExtensions.push 'OES_texture_half_float'\n            else\n                halfFloatTexturing = false\n                unshimExtensions.push 'OES_texture_half_float'\n\n        if halfFloatTexturing\n            extobj = gl.getExtension 'EXT_color_buffer_half_float'\n            if extobj == null\n                if checkColorBuffer gl, halfFloatExt.HALF_FLOAT_OES\n                    shimExtensions.push 'EXT_color_buffer_half_float'\n                    shimLookup.EXT_color_buffer_half_float = {\n                        shim: true\n                        RGBA16F_EXT: 0x881A\n                        RGB16F_EXT: 0x881B\n                        FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211\n                        UNSIGNED_NORMALIZED_EXT: 0x8C17\n                    }\n                else\n                    unshimExtensions.push 'EXT_color_buffer_half_float'\n            else\n                if checkColorBuffer gl, halfFloatExt.HALF_FLOAT_OES\n                    shimExtensions.push 'EXT_color_buffer_half_float'\n                else\n                    unshimExtensions.push 'EXT_color_buffer_half_float'\n            \n            extobj = gl.getExtension 'OES_texture_half_float_linear'\n            if extobj == null\n                if checkFloatLinear gl, halfFloatExt.HALF_FLOAT_OES\n                    shimExtensions.push 'OES_texture_half_float_linear'\n                    shimLookup.OES_texture_half_float_linear = {shim:true}\n                else\n                    unshimExtensions.push 'OES_texture_half_float_linear'\n            else\n                if checkFloatLinear gl, halfFloatExt.HALF_FLOAT_OES\n                    shimExtensions.push 'OES_texture_half_float_linear'\n                else\n                    unshimExtensions.push 'OES_texture_half_float_linear'\n   \nif window.WebGLRenderingContext?\n    checkSupport()\n\n    unshimLookup = {}\n    for name in unshimExtensions\n        unshimLookup[name] = true\n\n    getExtension = WebGLRenderingContext.prototype.getExtension\n    WebGLRenderingContext.prototype.getExtension = (name) ->\n        extobj = shimLookup[name]\n        if extobj == undefined\n            if unshimLookup[name]\n                return null\n            else\n                return getExtension.call @, name\n        else\n            return extobj\n    \n    getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions\n    WebGLRenderingContext.prototype.getSupportedExtensions = ->\n        supported = getSupportedExtensions.call(@)\n        result = []\n\n        for extension in supported\n            if unshimLookup[extension] == undefined\n                result.push(extension)\n\n        for extension in shimExtensions\n            if extension not in result\n                result.push extension\n\n        return result\n\n    WebGLRenderingContext.prototype.getFloatExtension = (spec) ->\n        spec.prefer ?= ['half']\n        spec.require ?= []\n        spec.throws ?= true\n\n        singleTexture = @getExtension 'OES_texture_float'\n        halfTexture = @getExtension 'OES_texture_half_float'\n        singleFramebuffer = @getExtension 'WEBGL_color_buffer_float'\n        halfFramebuffer = @getExtension 'EXT_color_buffer_half_float'\n        singleLinear = @getExtension 'OES_texture_float_linear'\n        halfLinear = @getExtension 'OES_texture_half_float_linear'\n\n        single = {\n            texture: singleTexture != null\n            filterable: singleLinear != null\n            renderable: singleFramebuffer != null\n            score: 0\n            precision: 'single'\n            half: false\n            single: true\n            type: @FLOAT\n        }\n        \n        half = {\n            texture: halfTexture != null\n            filterable: halfLinear != null\n            renderable: halfFramebuffer != null\n            score: 0\n            precision: 'half'\n            half: true\n            single: false\n            type: halfTexture?.HALF_FLOAT_OES ? null\n        }\n\n        candidates = []\n        if single.texture\n            candidates.push(single)\n        if half.texture\n            candidates.push(half)\n\n        result = []\n        for candidate in candidates\n            use = true\n            for name in spec.require\n                if candidate[name] == false\n                    use = false\n            if use\n                result.push candidate\n\n        for candidate in result\n            for preference, i in spec.prefer\n                importance = Math.pow 2, spec.prefer.length - i - 1\n                if candidate[preference]\n                    candidate.score += importance\n\n        result.sort (a, b) ->\n            if a.score == b.score then 0\n            else if a.score < b.score then 1\n            else if a.score > b.score then -1\n\n        if result.length == 0\n            if spec.throws\n                throw 'No floating point texture support that is ' + spec.require.join(', ')\n            else\n                return null\n        else\n            result = result[0]\n            return {\n                filterable: result.filterable\n                renderable: result.renderable\n                type: result.type\n                precision: result.precision\n            }\n"
  },
  {
    "path": "lib/webgl-texture-float-extension-shims.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar checkColorBuffer, checkFloatLinear, checkSupport, checkTexture, createSourceCanvas, getExtension, getSupportedExtensions, name, shimExtensions, shimLookup, unshimExtensions, unshimLookup, _i, _len,\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\ncreateSourceCanvas = function() {\n  var canvas, ctx, imageData;\n  canvas = document.createElement('canvas');\n  canvas.width = 2;\n  canvas.height = 2;\n  ctx = canvas.getContext('2d');\n  imageData = ctx.getImageData(0, 0, 2, 2);\n  imageData.data.set(new Uint8ClampedArray([0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255]));\n  ctx.putImageData(imageData, 0, 0);\n  return canvas;\n};\n\ncreateSourceCanvas();\n\ncheckFloatLinear = function(gl, sourceType) {\n  var buffer, cleanup, fragmentShader, framebuffer, positionLoc, program, readBuffer, result, source, sourceCanvas, sourceLoc, target, vertexShader, vertices;\n  program = gl.createProgram();\n  vertexShader = gl.createShader(gl.VERTEX_SHADER);\n  gl.attachShader(program, vertexShader);\n  gl.shaderSource(vertexShader, 'attribute vec2 position;\\nvoid main(){\\n    gl_Position = vec4(position, 0.0, 1.0);\\n}');\n  gl.compileShader(vertexShader);\n  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n    throw gl.getShaderInfoLog(vertexShader);\n  }\n  fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n  gl.attachShader(program, fragmentShader);\n  gl.shaderSource(fragmentShader, 'uniform sampler2D source;\\nvoid main(){\\n    gl_FragColor = texture2D(source, vec2(1.0, 1.0));\\n}');\n  gl.compileShader(fragmentShader);\n  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n    throw gl.getShaderInfoLog(fragmentShader);\n  }\n  gl.linkProgram(program);\n  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n    throw gl.getProgramInfoLog(program);\n  }\n  gl.useProgram(program);\n  cleanup = function() {\n    gl.deleteShader(fragmentShader);\n    gl.deleteShader(vertexShader);\n    gl.deleteProgram(program);\n    gl.deleteBuffer(buffer);\n    gl.deleteTexture(source);\n    gl.deleteTexture(target);\n    gl.deleteFramebuffer(framebuffer);\n    gl.bindBuffer(gl.ARRAY_BUFFER, null);\n    gl.useProgram(null);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n    return gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n  };\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n  framebuffer = gl.createFramebuffer();\n  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);\n  sourceCanvas = createSourceCanvas();\n  source = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, source);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, sourceType, sourceCanvas);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n  vertices = new Float32Array([1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1]);\n  buffer = gl.createBuffer();\n  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);\n  positionLoc = gl.getAttribLocation(program, 'position');\n  sourceLoc = gl.getUniformLocation(program, 'source');\n  gl.enableVertexAttribArray(positionLoc);\n  gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);\n  gl.uniform1i(sourceLoc, 0);\n  gl.drawArrays(gl.TRIANGLES, 0, 6);\n  readBuffer = new Uint8Array(4 * 4);\n  gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, readBuffer);\n  result = Math.abs(readBuffer[0] - 127) < 10;\n  cleanup();\n  return result;\n};\n\ncheckTexture = function(gl, targetType) {\n  var target;\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, targetType, null);\n  if (gl.getError() === 0) {\n    gl.deleteTexture(target);\n    return true;\n  } else {\n    gl.deleteTexture(target);\n    return false;\n  }\n};\n\ncheckColorBuffer = function(gl, targetType) {\n  var check, framebuffer, target;\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, targetType, null);\n  framebuffer = gl.createFramebuffer();\n  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);\n  check = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n  gl.deleteTexture(target);\n  gl.deleteFramebuffer(framebuffer);\n  gl.bindTexture(gl.TEXTURE_2D, null);\n  gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n  if (check === gl.FRAMEBUFFER_COMPLETE) {\n    return true;\n  } else {\n    return false;\n  }\n};\n\nshimExtensions = [];\n\nshimLookup = {};\n\nunshimExtensions = [];\n\ncheckSupport = function() {\n  var canvas, extobj, gl, halfFloatExt, halfFloatTexturing, singleFloatExt, singleFloatTexturing;\n  canvas = document.createElement('canvas');\n  gl = null;\n  try {\n    gl = canvas.getContext('experimental-webgl');\n    if (gl === null) {\n      gl = canvas.getContext('webgl');\n    }\n  } catch (_error) {}\n  if (gl != null) {\n    singleFloatExt = gl.getExtension('OES_texture_float');\n    if (singleFloatExt === null) {\n      if (checkTexture(gl, gl.FLOAT)) {\n        singleFloatTexturing = true;\n        shimExtensions.push('OES_texture_float');\n        shimLookup.OES_texture_float = {\n          shim: true\n        };\n      } else {\n        singleFloatTexturing = false;\n        unshimExtensions.push('OES_texture_float');\n      }\n    } else {\n      if (checkTexture(gl, gl.FLOAT)) {\n        singleFloatTexturing = true;\n        shimExtensions.push('OES_texture_float');\n      } else {\n        singleFloatTexturing = false;\n        unshimExtensions.push('OES_texture_float');\n      }\n    }\n    if (singleFloatTexturing) {\n      extobj = gl.getExtension('WEBGL_color_buffer_float');\n      if (extobj === null) {\n        if (checkColorBuffer(gl, gl.FLOAT)) {\n          shimExtensions.push('WEBGL_color_buffer_float');\n          shimLookup.WEBGL_color_buffer_float = {\n            shim: true,\n            RGBA32F_EXT: 0x8814,\n            RGB32F_EXT: 0x8815,\n            FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211,\n            UNSIGNED_NORMALIZED_EXT: 0x8C17\n          };\n        } else {\n          unshimExtensions.push('WEBGL_color_buffer_float');\n        }\n      } else {\n        if (checkColorBuffer(gl, gl.FLOAT)) {\n          shimExtensions.push('WEBGL_color_buffer_float');\n        } else {\n          unshimExtensions.push('WEBGL_color_buffer_float');\n        }\n      }\n      extobj = gl.getExtension('OES_texture_float_linear');\n      if (extobj === null) {\n        if (checkFloatLinear(gl, gl.FLOAT)) {\n          shimExtensions.push('OES_texture_float_linear');\n          shimLookup.OES_texture_float_linear = {\n            shim: true\n          };\n        } else {\n          unshimExtensions.push('OES_texture_float_linear');\n        }\n      } else {\n        if (checkFloatLinear(gl, gl.FLOAT)) {\n          shimExtensions.push('OES_texture_float_linear');\n        } else {\n          unshimExtensions.push('OES_texture_float_linear');\n        }\n      }\n    }\n    halfFloatExt = gl.getExtension('OES_texture_half_float');\n    if (halfFloatExt === null) {\n      if (checkTexture(gl, 0x8D61)) {\n        halfFloatTexturing = true;\n        shimExtensions.push('OES_texture_half_float');\n        halfFloatExt = shimLookup.OES_texture_half_float = {\n          HALF_FLOAT_OES: 0x8D61,\n          shim: true\n        };\n      } else {\n        halfFloatTexturing = false;\n        unshimExtensions.push('OES_texture_half_float');\n      }\n    } else {\n      if (checkTexture(gl, halfFloatExt.HALF_FLOAT_OES)) {\n        halfFloatTexturing = true;\n        shimExtensions.push('OES_texture_half_float');\n      } else {\n        halfFloatTexturing = false;\n        unshimExtensions.push('OES_texture_half_float');\n      }\n    }\n    if (halfFloatTexturing) {\n      extobj = gl.getExtension('EXT_color_buffer_half_float');\n      if (extobj === null) {\n        if (checkColorBuffer(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('EXT_color_buffer_half_float');\n          shimLookup.EXT_color_buffer_half_float = {\n            shim: true,\n            RGBA16F_EXT: 0x881A,\n            RGB16F_EXT: 0x881B,\n            FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211,\n            UNSIGNED_NORMALIZED_EXT: 0x8C17\n          };\n        } else {\n          unshimExtensions.push('EXT_color_buffer_half_float');\n        }\n      } else {\n        if (checkColorBuffer(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('EXT_color_buffer_half_float');\n        } else {\n          unshimExtensions.push('EXT_color_buffer_half_float');\n        }\n      }\n      extobj = gl.getExtension('OES_texture_half_float_linear');\n      if (extobj === null) {\n        if (checkFloatLinear(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('OES_texture_half_float_linear');\n          return shimLookup.OES_texture_half_float_linear = {\n            shim: true\n          };\n        } else {\n          return unshimExtensions.push('OES_texture_half_float_linear');\n        }\n      } else {\n        if (checkFloatLinear(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          return shimExtensions.push('OES_texture_half_float_linear');\n        } else {\n          return unshimExtensions.push('OES_texture_half_float_linear');\n        }\n      }\n    }\n  }\n};\n\nif (window.WebGLRenderingContext != null) {\n  checkSupport();\n  unshimLookup = {};\n  for (_i = 0, _len = unshimExtensions.length; _i < _len; _i++) {\n    name = unshimExtensions[_i];\n    unshimLookup[name] = true;\n  }\n  getExtension = WebGLRenderingContext.prototype.getExtension;\n  WebGLRenderingContext.prototype.getExtension = function(name) {\n    var extobj;\n    extobj = shimLookup[name];\n    if (extobj === void 0) {\n      if (unshimLookup[name]) {\n        return null;\n      } else {\n        return getExtension.call(this, name);\n      }\n    } else {\n      return extobj;\n    }\n  };\n  getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;\n  WebGLRenderingContext.prototype.getSupportedExtensions = function() {\n    var extension, result, supported, _j, _k, _len1, _len2;\n    supported = getSupportedExtensions.call(this);\n    result = [];\n    for (_j = 0, _len1 = supported.length; _j < _len1; _j++) {\n      extension = supported[_j];\n      if (unshimLookup[extension] === void 0) {\n        result.push(extension);\n      }\n    }\n    for (_k = 0, _len2 = shimExtensions.length; _k < _len2; _k++) {\n      extension = shimExtensions[_k];\n      if (__indexOf.call(result, extension) < 0) {\n        result.push(extension);\n      }\n    }\n    return result;\n  };\n  WebGLRenderingContext.prototype.getFloatExtension = function(spec) {\n    var candidate, candidates, half, halfFramebuffer, halfLinear, halfTexture, i, importance, preference, result, single, singleFramebuffer, singleLinear, singleTexture, use, _j, _k, _l, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;\n    if ((_ref = spec.prefer) == null) {\n      spec.prefer = ['half'];\n    }\n    if ((_ref1 = spec.require) == null) {\n      spec.require = [];\n    }\n    if ((_ref2 = spec.throws) == null) {\n      spec.throws = true;\n    }\n    singleTexture = this.getExtension('OES_texture_float');\n    halfTexture = this.getExtension('OES_texture_half_float');\n    singleFramebuffer = this.getExtension('WEBGL_color_buffer_float');\n    halfFramebuffer = this.getExtension('EXT_color_buffer_half_float');\n    singleLinear = this.getExtension('OES_texture_float_linear');\n    halfLinear = this.getExtension('OES_texture_half_float_linear');\n    single = {\n      texture: singleTexture !== null,\n      filterable: singleLinear !== null,\n      renderable: singleFramebuffer !== null,\n      score: 0,\n      precision: 'single',\n      half: false,\n      single: true,\n      type: this.FLOAT\n    };\n    half = {\n      texture: halfTexture !== null,\n      filterable: halfLinear !== null,\n      renderable: halfFramebuffer !== null,\n      score: 0,\n      precision: 'half',\n      half: true,\n      single: false,\n      type: (_ref3 = halfTexture != null ? halfTexture.HALF_FLOAT_OES : void 0) != null ? _ref3 : null\n    };\n    candidates = [];\n    if (single.texture) {\n      candidates.push(single);\n    }\n    if (half.texture) {\n      candidates.push(half);\n    }\n    result = [];\n    for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) {\n      candidate = candidates[_j];\n      use = true;\n      _ref4 = spec.require;\n      for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {\n        name = _ref4[_k];\n        if (candidate[name] === false) {\n          use = false;\n        }\n      }\n      if (use) {\n        result.push(candidate);\n      }\n    }\n    for (_l = 0, _len3 = result.length; _l < _len3; _l++) {\n      candidate = result[_l];\n      _ref5 = spec.prefer;\n      for (i = _m = 0, _len4 = _ref5.length; _m < _len4; i = ++_m) {\n        preference = _ref5[i];\n        importance = Math.pow(2, spec.prefer.length - i - 1);\n        if (candidate[preference]) {\n          candidate.score += importance;\n        }\n      }\n    }\n    result.sort(function(a, b) {\n      if (a.score === b.score) {\n        return 0;\n      } else if (a.score < b.score) {\n        return 1;\n      } else if (a.score > b.score) {\n        return -1;\n      }\n    });\n    if (result.length === 0) {\n      if (spec.throws) {\n        throw 'No floating point texture support that is ' + spec.require.join(', ');\n      } else {\n        return null;\n      }\n    } else {\n      result = result[0];\n      return {\n        filterable: result.filterable,\n        renderable: result.renderable,\n        type: result.type,\n        precision: result.precision\n      };\n    }\n  };\n}\n"
  },
  {
    "path": "license/bsd-license",
    "content": "Copyright (c) 2012, Florian Boesch <pyalot@gmail.com> http://codeflow.org/\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\nNeither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "license/gplv2-license",
    "content": "        GNU GENERAL PUBLIC LICENSE\n           Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n          Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n        GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n          NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n"
  },
  {
    "path": "license/gplv3-license",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "license/mit-license",
    "content": "Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>\nhttp://codeflow.com/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "license/readme",
    "content": "Copyright (c) 2012, Florian Boesch <pyalot@gmail.com> http://codeflow.org/\n\nDeferred Irradiance Volumes is licensed under any of the following licenses at your choosing:\n\nMIT: see mit-license\nGPL: see gplv*-license\nBSD: see bsd-license\n"
  },
  {
    "path": "pack",
    "content": "#!/usr/bin/env python\n\nimport os, sys, struct, cjson, stat\nfrom os.path import join\n\nhere = os.path.dirname(os.path.abspath(__file__))\n\nglobal_shunts = '''\nFunction.prototype.property = function(prop, desc) {\n    Object.defineProperty(this.prototype, prop, desc);\n};\n'''\n\ndef packModules(path):\n    result = ''\n    template = '''\n    loader.define('%s', function(exports, require, get){\n    %s});\n    '''\n    fs_base = join(here, path)\n    for path, dirs, names in os.walk(fs_base):\n        relpath = path[len(fs_base):]\n        if not relpath.startswith('/'):\n            relpath = '/' + relpath\n\n        for name in names:\n            if name.endswith('.js'):\n                packpath = join(relpath, name)\n                fspath = join(path, name)\n                data = open(fspath).read()\n                module = template % (packpath, data)\n                result += module\n    return result\n\ndef packCode(app, target, targetname):\n    if not requireCodePack([app, 'extra', 'lib'], target, targetname):\n        return\n\n    print 'packing code: %s' % target\n    result = ''\n    result += global_shunts\n    for path, dirs, names in os.walk(join(here, 'extra')):\n        for name in names:\n            if name.endswith('.js'):\n                data = open(join(path, name)).read()\n                result += '\\n%s;\\n' % data\n\n    result += packModules(app)\n    result += packModules('lib')\n\n    result += '\\n$(function(){loader.main()});'\n    open(join(here, target, targetname), 'w').write(result)\n\ndef requireCodePack(apps, target, targetname):\n    target_path = join(here, target, targetname)\n    if not os.path.exists(target_path):\n        return True\n\n    for app in apps:\n        target_mtime = os.stat(target_path)[stat.ST_MTIME]\n        for path, dirs, names in os.walk(join(here, app)):\n            for name in names:\n                if name.endswith('.js'):\n                    code_mtime = os.stat(join(path, name))[stat.ST_MTIME]\n                    if code_mtime > target_mtime:\n                        return True\n    return False\n\nbinary_types = [\n    'png', 'jpg', 'ogg',\n    'indices', 'vertices', 'model', 'mesh', 'bones',\n]\ntext_types = ['txt', 'shader', 'shaderlib']\npacktypes = binary_types + text_types + ['json']\n\ndef requireAssetPack(app, target, targetname):\n    for app in [app, 'lib']:\n        fs_base = join(here, app)\n        target_path = join(here, target, targetname)\n        if not os.path.exists(target_path):\n            return True\n        target_mtime = os.stat(target_path)[stat.ST_MTIME]\n     \n        for path, dirs, names in os.walk(fs_base):\n            for name in names:\n                ext = os.path.splitext(name)[1].lstrip('.')\n                fspath = join(path, name)\n                if ext in packtypes:\n                    asset_mtime = os.stat(fspath)[stat.ST_MTIME]\n                    if asset_mtime > target_mtime:\n                        return True\n    return False\n\ndef packAssets(app, target, targetname):\n    if not requireAssetPack(app, target, targetname):\n        return\n\n    print 'packing assets: %s' % target\n    chunks = ''\n    meta = {}\n    for app in [app, 'lib']:\n        fs_base = join(here, app)\n        for path, dirs, names in os.walk(fs_base):\n            relpath = path[len(fs_base):]\n            if not relpath.startswith('/'):\n                relpath = '/' + relpath\n            for name in names:\n                ext = os.path.splitext(name)[1].lstrip('.')\n                packpath = join(relpath, name)\n                fspath = join(path, name)\n                if ext in binary_types:\n                    data = open(fspath, 'rb').read()\n                    offset = len(chunks)\n                    size = len(data)\n                    chunks += data\n                    meta[packpath] = {\n                        'offset': offset,\n                        'size': size,\n                    }\n                elif ext in text_types:\n                    meta[packpath] = open(fspath, 'r').read()\n                elif ext == 'json':\n                    meta[packpath] = cjson.decode(open(fspath, 'r').read())\n\n    metadata = cjson.encode(meta)\n    metasize = struct.pack('I', len(metadata))\n    open(join(here, target, targetname), 'wb').write('PACK'+metasize+metadata+chunks)\n\ndef pack(app, target, codename=None, assetname=None):\n    if codename:\n        packCode(app, target, codename)\n    if assetname:\n        packAssets(app, target, assetname)\n\nif __name__ == '__main__':\n    pack('src', 'www', 'code.js', 'assets.pack')\n"
  },
  {
    "path": "src/albedo.shader",
    "content": "varying vec2 vTexcoord;\nvarying vec3 vPosition, vViewPosition, vNormal;\nuniform mat4 proj, view;\nuniform mat3 view_rot;\n\nvertex:\n    attribute vec3 position, normal;\n    attribute vec2 texcoord;\n\n    void main(){\n        vTexcoord = texcoord;\n        vPosition = position;\n        vNormal = normal;\n        vViewPosition = (view * vec4(position, 1.0)).xyz;\n\n        gl_Position = proj * view * vec4(position, 1.0);\n    }\n\nfragment:\n    uniform sampler2D diffuse_texture;\n    uniform float specularity;\n    uniform vec3 diffuse_color;\n    uniform float gamma;\n    void main(){\n        vec3 diffuse = pow(texture2D(diffuse_texture, vTexcoord).rgb, vec3(gamma));\n        gl_FragColor = vec4(diffuse*pow(diffuse_color, vec3(gamma)), 1.0);\n    }\n"
  },
  {
    "path": "src/antialias/fxaa2_0.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D source;\n    uniform vec2 viewport;\n    \n    #define FXAA_REDUCE_MIN   (1.0/ 128.0)\n    #define FXAA_REDUCE_MUL   (1.0 / 8.0)\n    #define FXAA_SPAN_MAX     8.0\n\n    vec4 fxaa(vec2 fragCoord, sampler2D tex)\n    {\n        vec4 color;\n        vec2 inverseVP = vec2(1.0 / viewport.x, 1.0 / viewport.y);\n        vec3 rgbNW = texture2D(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;\n        vec3 rgbNE = texture2D(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;\n        vec3 rgbSW = texture2D(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;\n        vec3 rgbSE = texture2D(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;\n        vec3 rgbM  = texture2D(tex, fragCoord  * inverseVP).xyz;\n        vec3 luma = vec3(0.299, 0.587, 0.114);\n        float lumaNW = dot(rgbNW, luma);\n        float lumaNE = dot(rgbNE, luma);\n        float lumaSW = dot(rgbSW, luma);\n        float lumaSE = dot(rgbSE, luma);\n        float lumaM  = dot(rgbM,  luma);\n        float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n        float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n        \n        vec2 dir;\n        dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n        dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n        \n        float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\n                              (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n        \n        float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n        dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n                  max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n                  dir * rcpDirMin)) * inverseVP;\n          \n        vec3 rgbA = 0.5 * (\n            texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\n            texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n        vec3 rgbB = rgbA * 0.5 + 0.25 * (\n            texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\n            texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\n        float lumaB = dot(rgbB, luma);\n        if ((lumaB < lumaMin) || (lumaB > lumaMax))\n            color = vec4(rgbA, 1.0);\n        else\n            color = vec4(rgbB, 1.0);\n        return color;\n    }\n        \n    void main(){\n        gl_FragColor = vec4(fxaa(gl_FragCoord.xy, source).rgb, 1.0);\n    }\n"
  },
  {
    "path": "src/antialias/fxaa3_11.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    #define FXAA_WebGL 1\n    //#require fxaa3_11\n    //#require fxaa3_11_stripped\n    #require fxaa3_11_preprocessed\n\n    uniform sampler2D source;\n    uniform vec2 viewport;\n    uniform float subpixel_aa, contrast_treshold, edge_treshold;\n\n    void main(){\n        vec4 color = FxaaPixelShader(\n            gl_FragCoord.xy/viewport,\n            source,\n            vec2(1.0)/viewport,\n            subpixel_aa,\n            contrast_treshold,\n            edge_treshold \n        );\n        gl_FragColor = vec4(color.rgb, 1.0);\n    }\n\n"
  },
  {
    "path": "src/antialias/fxaa3_11.shaderlib",
    "content": "/*============================================================================\n\n\n                    NVIDIA FXAA 3.11 by TIMOTHY LOTTES\n\n\n------------------------------------------------------------------------------\nCOPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED.\n------------------------------------------------------------------------------\nTO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED\n*AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA\nOR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR\nCONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR\nLOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION,\nOR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE\nTHIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH\nDAMAGES.\n\n------------------------------------------------------------------------------\n                           INTEGRATION CHECKLIST\n------------------------------------------------------------------------------\n(1.)\nIn the shader source, setup defines for the desired configuration.\nWhen providing multiple shaders (for different presets),\nsimply setup the defines differently in multiple files.\nExample,\n\n  #define FXAA_PC 1\n  #define FXAA_HLSL_5 1\n  #define FXAA_QUALITY__PRESET 12\n\nOr,\n\n  #define FXAA_360 1\n  \nOr,\n\n  #define FXAA_PS3 1\n  \nEtc.\n\n(2.)\nThen include this file,\n\n  #include \"Fxaa3_11.h\"\n\n(3.)\nThen call the FXAA pixel shader from within your desired shader.\nLook at the FXAA Quality FxaaPixelShader() for docs on inputs.\nAs for FXAA 3.11 all inputs for all shaders are the same \nto enable easy porting between platforms.\n\n  return FxaaPixelShader(...);\n\n(4.)\nInsure pass prior to FXAA outputs RGBL (see next section).\nOr use,\n\n  #define FXAA_GREEN_AS_LUMA 1\n\n(5.)\nSetup engine to provide the following constants\nwhich are used in the FxaaPixelShader() inputs,\n\n  FxaaFloat2 fxaaQualityRcpFrame,\n  FxaaFloat4 fxaaConsoleRcpFrameOpt,\n  FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n  FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n  FxaaFloat fxaaQualitySubpix,\n  FxaaFloat fxaaQualityEdgeThreshold,\n  FxaaFloat fxaaQualityEdgeThresholdMin,\n  FxaaFloat fxaaConsoleEdgeSharpness,\n  FxaaFloat fxaaConsoleEdgeThreshold,\n  FxaaFloat fxaaConsoleEdgeThresholdMin,\n  FxaaFloat4 fxaaConsole360ConstDir\n\nLook at the FXAA Quality FxaaPixelShader() for docs on inputs.\n\n(6.)\nHave FXAA vertex shader run as a full screen triangle,\nand output \"pos\" and \"fxaaConsolePosPos\" \nsuch that inputs in the pixel shader provide,\n\n  // {xy} = center of pixel\n  FxaaFloat2 pos,\n\n  // {xy__} = upper left of pixel\n  // {__zw} = lower right of pixel\n  FxaaFloat4 fxaaConsolePosPos,\n\n(7.)\nInsure the texture sampler(s) used by FXAA are set to bilinear filtering.\n\n\n------------------------------------------------------------------------------\n                    INTEGRATION - RGBL AND COLORSPACE\n------------------------------------------------------------------------------\nFXAA3 requires RGBL as input unless the following is set, \n\n  #define FXAA_GREEN_AS_LUMA 1\n\nIn which case the engine uses green in place of luma,\nand requires RGB input is in a non-linear colorspace.\n\nRGB should be LDR (low dynamic range).\nSpecifically do FXAA after tonemapping.\n\nRGB data as returned by a texture fetch can be non-linear,\nor linear when FXAA_GREEN_AS_LUMA is not set.\nNote an \"sRGB format\" texture counts as linear,\nbecause the result of a texture fetch is linear data.\nRegular \"RGBA8\" textures in the sRGB colorspace are non-linear.\n\nIf FXAA_GREEN_AS_LUMA is not set,\nluma must be stored in the alpha channel prior to running FXAA.\nThis luma should be in a perceptual space (could be gamma 2.0).\nExample pass before FXAA where output is gamma 2.0 encoded,\n\n  color.rgb = ToneMap(color.rgb); // linear color output\n  color.rgb = sqrt(color.rgb);    // gamma 2.0 color output\n  return color;\n\nTo use FXAA,\n\n  color.rgb = ToneMap(color.rgb);  // linear color output\n  color.rgb = sqrt(color.rgb);     // gamma 2.0 color output\n  color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma\n  return color;\n\nAnother example where output is linear encoded,\nsay for instance writing to an sRGB formated render target,\nwhere the render target does the conversion back to sRGB after blending,\n\n  color.rgb = ToneMap(color.rgb); // linear color output\n  return color;\n\nTo use FXAA,\n\n  color.rgb = ToneMap(color.rgb); // linear color output\n  color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma\n  return color;\n\nGetting luma correct is required for the algorithm to work correctly.\n\n\n------------------------------------------------------------------------------\n                          BEING LINEARLY CORRECT?\n------------------------------------------------------------------------------\nApplying FXAA to a framebuffer with linear RGB color will look worse.\nThis is very counter intuitive, but happends to be true in this case.\nThe reason is because dithering artifacts will be more visiable \nin a linear colorspace.\n\n\n------------------------------------------------------------------------------\n                             COMPLEX INTEGRATION\n------------------------------------------------------------------------------\nQ. What if the engine is blending into RGB before wanting to run FXAA?\n\nA. In the last opaque pass prior to FXAA,\n   have the pass write out luma into alpha.\n   Then blend into RGB only.\n   FXAA should be able to run ok\n   assuming the blending pass did not any add aliasing.\n   This should be the common case for particles and common blending passes.\n\nA. Or use FXAA_GREEN_AS_LUMA.\n\n============================================================================*/\n\n/*============================================================================\n\n                             INTEGRATION KNOBS\n\n============================================================================*/\n//\n// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).\n// FXAA_360_OPT is a prototype for the new optimized 360 version.\n//\n// 1 = Use API.\n// 0 = Don't use API.\n//\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_PS3\n    #define FXAA_PS3 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_360\n    #define FXAA_360 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_360_OPT\n    #define FXAA_360_OPT 0\n#endif\n/*==========================================================================*/\n#ifndef FXAA_PC\n    //\n    // FXAA Quality\n    // The high quality PC algorithm.\n    //\n    #define FXAA_PC 1\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_PC_CONSOLE\n    //\n    // The console algorithm for PC is included\n    // for developers targeting really low spec machines.\n    // Likely better to just run FXAA_PC, and use a really low preset.\n    //\n    #define FXAA_PC_CONSOLE 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_GLSL_120\n    #define FXAA_GLSL_120 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_GLSL_130\n    #define FXAA_GLSL_130 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_HLSL_3\n    #define FXAA_HLSL_3 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_HLSL_4\n    #define FXAA_HLSL_4 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_HLSL_5\n    #define FXAA_HLSL_5 0\n#endif\n/*==========================================================================*/\n#ifndef FXAA_GREEN_AS_LUMA\n    //\n    // For those using non-linear color,\n    // and either not able to get luma in alpha, or not wanting to,\n    // this enables FXAA to run using green as a proxy for luma.\n    // So with this enabled, no need to pack luma in alpha.\n    //\n    // This will turn off AA on anything which lacks some amount of green.\n    // Pure red and blue or combination of only R and B, will get no AA.\n    //\n    // Might want to lower the settings for both,\n    //    fxaaConsoleEdgeThresholdMin\n    //    fxaaQualityEdgeThresholdMin\n    // In order to insure AA does not get turned off on colors \n    // which contain a minor amount of green.\n    //\n    // 1 = On.\n    // 0 = Off.\n    //\n    #define FXAA_GREEN_AS_LUMA 1\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_EARLY_EXIT\n    //\n    // Controls algorithm's early exit path.\n    // On PS3 turning this ON adds 2 cycles to the shader.\n    // On 360 turning this OFF adds 10ths of a millisecond to the shader.\n    // Turning this off on console will result in a more blurry image.\n    // So this defaults to on.\n    //\n    // 1 = On.\n    // 0 = Off.\n    //\n    #define FXAA_EARLY_EXIT 1\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_DISCARD\n    //\n    // Only valid for PC OpenGL currently.\n    // Probably will not work when FXAA_GREEN_AS_LUMA = 1.\n    //\n    // 1 = Use discard on pixels which don't need AA.\n    //     For APIs which enable concurrent TEX+ROP from same surface.\n    // 0 = Return unchanged color on pixels which don't need AA.\n    //\n    #define FXAA_DISCARD 0\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_FAST_PIXEL_OFFSET\n    //\n    // Used for GLSL 120 only.\n    //\n    // 1 = GL API supports fast pixel offsets\n    // 0 = do not use fast pixel offsets\n    //\n    #ifdef GL_EXT_gpu_shader4\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifdef GL_NV_gpu_shader5\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifdef GL_ARB_gpu_shader5\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifndef FXAA_FAST_PIXEL_OFFSET\n        #define FXAA_FAST_PIXEL_OFFSET 0\n    #endif\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_GATHER4_ALPHA\n    //\n    // 1 = API supports gather4 on alpha channel.\n    // 0 = API does not support gather4 on alpha channel.\n    //\n    #if (FXAA_HLSL_5 == 1)\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifdef GL_ARB_gpu_shader5\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifdef GL_NV_gpu_shader5\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifndef FXAA_GATHER4_ALPHA\n        #define FXAA_GATHER4_ALPHA 0\n    #endif\n#endif\n\n/*============================================================================\n                      FXAA CONSOLE PS3 - TUNING KNOBS\n============================================================================*/\n#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS\n    //\n    // Consoles the sharpness of edges on PS3 only.\n    // Non-PS3 tuning is done with shader input.\n    //\n    // Due to the PS3 being ALU bound,\n    // there are only two safe values here: 4 and 8.\n    // These options use the shaders ability to a free *|/ by 2|4|8.\n    //\n    // 8.0 is sharper\n    // 4.0 is softer\n    // 2.0 is really soft (good for vector graphics inputs)\n    //\n    #if 1\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0\n    #endif\n    #if 0\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0\n    #endif\n    #if 0\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0\n    #endif\n#endif\n/*--------------------------------------------------------------------------*/\n#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD\n    //\n    // Only effects PS3.\n    // Non-PS3 tuning is done with shader input.\n    //\n    // The minimum amount of local contrast required to apply algorithm.\n    // The console setting has a different mapping than the quality setting.\n    //\n    // This only applies when FXAA_EARLY_EXIT is 1.\n    //\n    // Due to the PS3 being ALU bound,\n    // there are only two safe values here: 0.25 and 0.125.\n    // These options use the shaders ability to a free *|/ by 2|4|8.\n    //\n    // 0.125 leaves less aliasing, but is softer\n    // 0.25 leaves more aliasing, and is sharper\n    //\n    #if 1\n        #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125\n    #else\n        #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25\n    #endif\n#endif\n\n/*============================================================================\n                        FXAA QUALITY - TUNING KNOBS\n------------------------------------------------------------------------------\nNOTE the other tuning knobs are now in the shader function inputs!\n============================================================================*/\n#ifndef FXAA_QUALITY__PRESET\n    //\n    // Choose the quality preset.\n    // This needs to be compiled into the shader as it effects code.\n    // Best option to include multiple presets is to \n    // in each shader define the preset, then include this file.\n    // \n    // OPTIONS\n    // -----------------------------------------------------------------------\n    // 10 to 15 - default medium dither (10=fastest, 15=highest quality)\n    // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)\n    // 39       - no dither, very expensive \n    //\n    // NOTES\n    // -----------------------------------------------------------------------\n    // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)\n    // 13 = about same speed as FXAA 3.9 and better than 12\n    // 23 = closest to FXAA 3.9 visually and performance wise\n    //  _ = the lowest digit is directly related to performance\n    // _  = the highest digit is directly related to style\n    // \n    #define FXAA_QUALITY__PRESET 12\n#endif\n\n\n/*============================================================================\n\n                           FXAA QUALITY - PRESETS\n\n============================================================================*/\n\n/*============================================================================\n                     FXAA QUALITY - MEDIUM DITHER PRESETS\n============================================================================*/\n#if (FXAA_QUALITY__PRESET == 10)\n    #define FXAA_QUALITY__PS 3\n    #define FXAA_QUALITY__P0 1.5\n    #define FXAA_QUALITY__P1 3.0\n    #define FXAA_QUALITY__P2 12.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 11)\n    #define FXAA_QUALITY__PS 4\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 3.0\n    #define FXAA_QUALITY__P3 12.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 12)\n    #define FXAA_QUALITY__PS 5\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 4.0\n    #define FXAA_QUALITY__P4 12.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 13)\n    #define FXAA_QUALITY__PS 6\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 4.0\n    #define FXAA_QUALITY__P5 12.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 14)\n    #define FXAA_QUALITY__PS 7\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 4.0\n    #define FXAA_QUALITY__P6 12.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 15)\n    #define FXAA_QUALITY__PS 8\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 4.0\n    #define FXAA_QUALITY__P7 12.0\n#endif\n\n/*============================================================================\n                     FXAA QUALITY - LOW DITHER PRESETS\n============================================================================*/\n#if (FXAA_QUALITY__PRESET == 20)\n    #define FXAA_QUALITY__PS 3\n    #define FXAA_QUALITY__P0 1.5\n    #define FXAA_QUALITY__P1 2.0\n    #define FXAA_QUALITY__P2 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 21)\n    #define FXAA_QUALITY__PS 4\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 22)\n    #define FXAA_QUALITY__PS 5\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 23)\n    #define FXAA_QUALITY__PS 6\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 24)\n    #define FXAA_QUALITY__PS 7\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 3.0\n    #define FXAA_QUALITY__P6 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 25)\n    #define FXAA_QUALITY__PS 8\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 4.0\n    #define FXAA_QUALITY__P7 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 26)\n    #define FXAA_QUALITY__PS 9\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 4.0\n    #define FXAA_QUALITY__P8 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 27)\n    #define FXAA_QUALITY__PS 10\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 4.0\n    #define FXAA_QUALITY__P9 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 28)\n    #define FXAA_QUALITY__PS 11\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 4.0\n    #define FXAA_QUALITY__P10 8.0\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_QUALITY__PRESET == 29)\n    #define FXAA_QUALITY__PS 12\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 2.0\n    #define FXAA_QUALITY__P10 4.0\n    #define FXAA_QUALITY__P11 8.0\n#endif\n\n/*============================================================================\n                     FXAA QUALITY - EXTREME QUALITY\n============================================================================*/\n#if (FXAA_QUALITY__PRESET == 39)\n    #define FXAA_QUALITY__PS 12\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.0\n    #define FXAA_QUALITY__P2 1.0\n    #define FXAA_QUALITY__P3 1.0\n    #define FXAA_QUALITY__P4 1.0\n    #define FXAA_QUALITY__P5 1.5\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 2.0\n    #define FXAA_QUALITY__P10 4.0\n    #define FXAA_QUALITY__P11 8.0\n#endif\n\n\n\n/*============================================================================\n\n                                API PORTING\n\n============================================================================*/\n#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) || (FXAA_WebGL == 1)\n    #define FxaaBool bool\n    #define FxaaDiscard discard\n    #define FxaaFloat float\n    #define FxaaFloat2 vec2\n    #define FxaaFloat3 vec3\n    #define FxaaFloat4 vec4\n    #define FxaaHalf float\n    #define FxaaHalf2 vec2\n    #define FxaaHalf3 vec3\n    #define FxaaHalf4 vec4\n    #define FxaaInt2 ivec2\n    #define FxaaSat(x) clamp(x, 0.0, 1.0)\n    #define FxaaTex sampler2D\n#else\n    #define FxaaBool bool\n    #define FxaaDiscard clip(-1)\n    #define FxaaFloat float\n    #define FxaaFloat2 float2\n    #define FxaaFloat3 float3\n    #define FxaaFloat4 float4\n    #define FxaaHalf half\n    #define FxaaHalf2 half2\n    #define FxaaHalf3 half3\n    #define FxaaHalf4 half4\n    #define FxaaSat(x) saturate(x)\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_WebGL == 1)\n    #define FxaaTexTop(t, p) texture2D(t, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) texture2D(t, p + (vec2(o) * r), 0.0)\n#endif\n#if (FXAA_GLSL_120 == 1)\n    // Requires,\n    //  #version 120\n    // And at least,\n    //  #extension GL_EXT_gpu_shader4 : enable\n    //  (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)\n    // #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)\n    #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)\n    #if (FXAA_FAST_PIXEL_OFFSET == 1)\n        #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)\n    #else\n        #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)\n    #endif\n    #if (FXAA_GATHER4_ALPHA == 1)\n        // use #extension GL_ARB_gpu_shader5 : enable\n        #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)\n        #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)\n        #define FxaaTexGreen4(t, p) textureGather(t, p, 1)\n        #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)\n    #endif\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_GLSL_130 == 1)\n    // Requires \"#version 130\" or better\n    #define FxaaTexTop(t, p) textureLod(t, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)\n    #if (FXAA_GATHER4_ALPHA == 1)\n        // use #extension GL_ARB_gpu_shader5 : enable\n        #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)\n        #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)\n        #define FxaaTexGreen4(t, p) textureGather(t, p, 1)\n        #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)\n    #endif\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)\n    #define FxaaInt2 float2\n    #define FxaaTex sampler2D\n    #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))\n    #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_HLSL_4 == 1)\n    #define FxaaInt2 int2\n    struct FxaaTex { SamplerState smpl; Texture2D tex; };\n    #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)\n#endif\n/*--------------------------------------------------------------------------*/\n#if (FXAA_HLSL_5 == 1)\n    #define FxaaInt2 int2\n    struct FxaaTex { SamplerState smpl; Texture2D tex; };\n    #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)\n    #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)\n    #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)\n    #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)\n    #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)\n#endif\n\n\n/*============================================================================\n                   GREEN AS LUMA OPTION SUPPORT FUNCTION\n============================================================================*/\n#if (FXAA_GREEN_AS_LUMA == 0)\n    FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }\n#else\n    FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }\n#endif    \n\n\n\n\n/*============================================================================\n\n                             FXAA3 QUALITY - PC\n\n============================================================================*/\n#if (FXAA_PC == 1)\n/*--------------------------------------------------------------------------*/\nFxaaFloat4 FxaaPixelShader(\n    // Use noperspective interpolation here (turn off perspective interpolation).\n    // {xy} = center of pixel\n    FxaaFloat2 pos\n\n    #if (FXAA_PS3 == 1)\n        // Used only for FXAA Console, and not used on the 360 version.\n        // Use noperspective interpolation here (turn off perspective interpolation).\n        // {xy__} = upper left of pixel\n        // {__zw} = lower right of pixel\n        ,FxaaFloat4 fxaaConsolePosPos\n    #endif\n    \n    // Input color texture.\n    // {rgb_} = color in linear or perceptual color space\n    // if (FXAA_GREEN_AS_LUMA == 0)\n    //     {___a} = luma in perceptual color space (not linear)\n    ,FxaaTex tex\n\n    #if (FXAA_360_OPT == 1)\n        // Only used on the optimized 360 version of FXAA Console.\n        // For everything but 360, just use the same input here as for \"tex\".\n        // For 360, same texture, just alias with a 2nd sampler.\n        // This sampler needs to have an exponent bias of -1.\n        ,FxaaTex fxaaConsole360TexExpBiasNegOne\n    \n        // Only used on the optimized 360 version of FXAA Console.\n        // For everything but 360, just use the same input here as for \"tex\".\n        // For 360, same texture, just alias with a 3nd sampler.\n        // This sampler needs to have an exponent bias of -2.\n        ,FxaaTex fxaaConsole360TexExpBiasNegTwo\n    #endif\n    //\n    // Only used on FXAA Quality.\n    // This must be from a constant/uniform.\n    // {x_} = 1.0/screenWidthInPixels\n    // {_y} = 1.0/screenHeightInPixels\n    ,FxaaFloat2 fxaaQualityRcpFrame\n    #if (FXAA_PS3 == 1) || (FXAA_360 == 1) || (FXAA_360_OPT == 1) || (FXAA_PC_CONSOLE == 1)\n        //\n        // Only used on FXAA Console.\n        // This must be from a constant/uniform.\n        // This effects sub-pixel AA quality and inversely sharpness.\n        //   Where N ranges between,\n        //     N = 0.50 (default)\n        //     N = 0.33 (sharper)\n        // {x___} = -N/screenWidthInPixels  \n        // {_y__} = -N/screenHeightInPixels\n        // {__z_} =  N/screenWidthInPixels  \n        // {___w} =  N/screenHeightInPixels \n        ,FxaaFloat4 fxaaConsoleRcpFrameOpt\n        //\n        // Only used on FXAA Console.\n        // Not used on 360, but used on PS3 and PC.\n        // This must be from a constant/uniform.\n        // {x___} = -2.0/screenWidthInPixels  \n        // {_y__} = -2.0/screenHeightInPixels\n        // {__z_} =  2.0/screenWidthInPixels  \n        // {___w} =  2.0/screenHeightInPixels \n        ,FxaaFloat4 fxaaConsoleRcpFrameOpt2\n        //\n        // Only used on FXAA Console.\n        // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.\n        // This must be from a constant/uniform.\n        // {x___} =  8.0/screenWidthInPixels  \n        // {_y__} =  8.0/screenHeightInPixels\n        // {__z_} = -4.0/screenWidthInPixels  \n        // {___w} = -4.0/screenHeightInPixels \n        ,FxaaFloat4 fxaaConsole360RcpFrameOpt2\n    #endif\n    // Only used on FXAA Quality.\n    // This used to be the FXAA_QUALITY__SUBPIX define.\n    // It is here now to allow easier tuning.\n    // Choose the amount of sub-pixel aliasing removal.\n    // This can effect sharpness.\n    //   1.00 - upper limit (softer)\n    //   0.75 - default amount of filtering\n    //   0.50 - lower limit (sharper, less sub-pixel aliasing removal)\n    //   0.25 - almost off\n    //   0.00 - completely off\n    ,FxaaFloat fxaaQualitySubpix\n    //\n    // Only used on FXAA Quality.\n    // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.\n    // It is here now to allow easier tuning.\n    // The minimum amount of local contrast required to apply algorithm.\n    //   0.333 - too little (faster)\n    //   0.250 - low quality\n    //   0.166 - default\n    //   0.125 - high quality \n    //   0.063 - overkill (slower)\n    ,FxaaFloat fxaaQualityEdgeThreshold\n    //\n    // Only used on FXAA Quality.\n    // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.\n    // It is here now to allow easier tuning.\n    // Trims the algorithm from processing darks.\n    //   0.0833 - upper limit (default, the start of visible unfiltered edges)\n    //   0.0625 - high quality (faster)\n    //   0.0312 - visible limit (slower)\n    // Special notes when using FXAA_GREEN_AS_LUMA,\n    //   Likely want to set this to zero.\n    //   As colors that are mostly not-green\n    //   will appear very dark in the green channel!\n    //   Tune by looking at mostly non-green content,\n    //   then start at zero and increase until aliasing is a problem.\n    ,FxaaFloat fxaaQualityEdgeThresholdMin\n    #if (FXAA_PS3 == 1) || (FXAA_360 == 1) || (FXAA_360_OPT == 1) || (FXAA_PC_CONSOLE == 1)\n        // Only used on FXAA Console.\n        // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define.\n        // It is here now to allow easier tuning.\n        // This does not effect PS3, as this needs to be compiled in.\n        //   Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3.\n        //   Due to the PS3 being ALU bound,\n        //   there are only three safe values here: 2 and 4 and 8.\n        //   These options use the shaders ability to a free *|/ by 2|4|8.\n        // For all other platforms can be a non-power of two.\n        //   8.0 is sharper (default!!!)\n        //   4.0 is softer\n        //   2.0 is really soft (good only for vector graphics inputs)\n        ,FxaaFloat fxaaConsoleEdgeSharpness\n        //\n        // Only used on FXAA Console.\n        // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define.\n        // It is here now to allow easier tuning.\n        // This does not effect PS3, as this needs to be compiled in.\n        //   Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3.\n        //   Due to the PS3 being ALU bound,\n        //   there are only two safe values here: 1/4 and 1/8.\n        //   These options use the shaders ability to a free *|/ by 2|4|8.\n        // The console setting has a different mapping than the quality setting.\n        // Other platforms can use other values.\n        //   0.125 leaves less aliasing, but is softer (default!!!)\n        //   0.25 leaves more aliasing, and is sharper\n        ,FxaaFloat fxaaConsoleEdgeThreshold\n        //\n        // Only used on FXAA Console.\n        // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define.\n        // It is here now to allow easier tuning.\n        // Trims the algorithm from processing darks.\n        // The console setting has a different mapping than the quality setting.\n        // This only applies when FXAA_EARLY_EXIT is 1.\n        // This does not apply to PS3, \n        // PS3 was simplified to avoid more shader instructions.\n        //   0.06 - faster but more aliasing in darks\n        //   0.05 - default\n        //   0.04 - slower and less aliasing in darks\n        // Special notes when using FXAA_GREEN_AS_LUMA,\n        //   Likely want to set this to zero.\n        //   As colors that are mostly not-green\n        //   will appear very dark in the green channel!\n        //   Tune by looking at mostly non-green content,\n        //   then start at zero and increase until aliasing is a problem.\n        ,FxaaFloat fxaaConsoleEdgeThresholdMin\n    #endif\n\n    #if (FXAA_360 == 1) || (FXAA_360_OPT == 1)\n        // Extra constants for 360 FXAA Console only.\n        // Use zeros or anything else for other platforms.\n        // These must be in physical constant registers and NOT immedates.\n        // Immedates will result in compiler un-optimizing.\n        // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)\n        ,FxaaFloat4 fxaaConsole360ConstDir\n    #endif\n) {\n/*--------------------------------------------------------------------------*/\n    FxaaFloat2 posM;\n    posM.x = pos.x;\n    posM.y = pos.y;\n    #if (FXAA_GATHER4_ALPHA == 1)\n        #if (FXAA_DISCARD == 0)\n            FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);\n            #if (FXAA_GREEN_AS_LUMA == 0)\n                #define lumaM rgbyM.w\n            #else\n                #define lumaM rgbyM.y\n            #endif\n        #endif\n        #if (FXAA_GREEN_AS_LUMA == 0)\n            FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);\n            FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));\n        #else\n            FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);\n            FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));\n        #endif\n        #if (FXAA_DISCARD == 1)\n            #define lumaM luma4A.w\n        #endif\n        #define lumaE luma4A.z\n        #define lumaS luma4A.x\n        #define lumaSE luma4A.y\n        #define lumaNW luma4B.w\n        #define lumaN luma4B.z\n        #define lumaW luma4B.x\n    #else\n        FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);\n        #if (FXAA_GREEN_AS_LUMA == 0)\n            #define lumaM rgbyM.w\n        #else\n            #define lumaM rgbyM.y\n        #endif\n        FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));\n    #endif\n/*--------------------------------------------------------------------------*/\n    FxaaFloat maxSM = max(lumaS, lumaM);\n    FxaaFloat minSM = min(lumaS, lumaM);\n    FxaaFloat maxESM = max(lumaE, maxSM);\n    FxaaFloat minESM = min(lumaE, minSM);\n    FxaaFloat maxWN = max(lumaN, lumaW);\n    FxaaFloat minWN = min(lumaN, lumaW);\n    FxaaFloat rangeMax = max(maxWN, maxESM);\n    FxaaFloat rangeMin = min(minWN, minESM);\n    FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;\n    FxaaFloat range = rangeMax - rangeMin;\n    FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);\n    FxaaBool earlyExit = range < rangeMaxClamped;\n/*--------------------------------------------------------------------------*/\n    if(earlyExit)\n        #if (FXAA_DISCARD == 1)\n            FxaaDiscard;\n        #else\n            return rgbyM;\n        #endif\n/*--------------------------------------------------------------------------*/\n    #if (FXAA_GATHER4_ALPHA == 0)\n        FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));\n    #else\n        FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));\n    #endif\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaNS = lumaN + lumaS;\n    FxaaFloat lumaWE = lumaW + lumaE;\n    FxaaFloat subpixRcpRange = 1.0/range;\n    FxaaFloat subpixNSWE = lumaNS + lumaWE;\n    FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;\n    FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaNESE = lumaNE + lumaSE;\n    FxaaFloat lumaNWNE = lumaNW + lumaNE;\n    FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;\n    FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaNWSW = lumaNW + lumaSW;\n    FxaaFloat lumaSWSE = lumaSW + lumaSE;\n    FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);\n    FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);\n    FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;\n    FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;\n    FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;\n    FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;\n    FxaaFloat lengthSign = fxaaQualityRcpFrame.x;\n    FxaaBool horzSpan = edgeHorz >= edgeVert;\n    FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;\n/*--------------------------------------------------------------------------*/\n    if(!horzSpan) lumaN = lumaW;\n    if(!horzSpan) lumaS = lumaE;\n    if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;\n    FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat gradientN = lumaN - lumaM;\n    FxaaFloat gradientS = lumaS - lumaM;\n    FxaaFloat lumaNN = lumaN + lumaM;\n    FxaaFloat lumaSS = lumaS + lumaM;\n    FxaaBool pairN = abs(gradientN) >= abs(gradientS);\n    FxaaFloat gradient = max(abs(gradientN), abs(gradientS));\n    if(pairN) lengthSign = -lengthSign;\n    FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat2 posB;\n    posB.x = posM.x;\n    posB.y = posM.y;\n    FxaaFloat2 offNP;\n    offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n    offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n    if(!horzSpan) posB.x += lengthSign * 0.5;\n    if( horzSpan) posB.y += lengthSign * 0.5;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat2 posN;\n    posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;\n    posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;\n    FxaaFloat2 posP;\n    posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;\n    posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;\n    FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;\n    FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));\n    FxaaFloat subpixE = subpixC * subpixC;\n    FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));\n/*--------------------------------------------------------------------------*/\n    if(!pairN) lumaNN = lumaSS;\n    FxaaFloat gradientScaled = gradient * 1.0/4.0;\n    FxaaFloat lumaMM = lumaM - lumaNN * 0.5;\n    FxaaFloat subpixF = subpixD * subpixE;\n    FxaaBool lumaMLTZero = lumaMM < 0.0;\n/*--------------------------------------------------------------------------*/\n    lumaEndN -= lumaNN * 0.5;\n    lumaEndP -= lumaNN * 0.5;\n    FxaaBool doneN = abs(lumaEndN) >= gradientScaled;\n    FxaaBool doneP = abs(lumaEndP) >= gradientScaled;\n    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;\n    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;\n    FxaaBool doneNP = (!doneN) || (!doneP);\n    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;\n    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;\n/*--------------------------------------------------------------------------*/\n    if(doneNP) {\n        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n        doneN = abs(lumaEndN) >= gradientScaled;\n        doneP = abs(lumaEndP) >= gradientScaled;\n        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;\n        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;\n        doneNP = (!doneN) || (!doneP);\n        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;\n        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;\n/*--------------------------------------------------------------------------*/\n        #if (FXAA_QUALITY__PS > 3)\n        if(doneNP) {\n            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n            doneN = abs(lumaEndN) >= gradientScaled;\n            doneP = abs(lumaEndP) >= gradientScaled;\n            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;\n            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;\n            doneNP = (!doneN) || (!doneP);\n            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;\n            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;\n/*--------------------------------------------------------------------------*/\n            #if (FXAA_QUALITY__PS > 4)\n            if(doneNP) {\n                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                doneN = abs(lumaEndN) >= gradientScaled;\n                doneP = abs(lumaEndP) >= gradientScaled;\n                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;\n                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;\n                doneNP = (!doneN) || (!doneP);\n                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;\n                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;\n/*--------------------------------------------------------------------------*/\n                #if (FXAA_QUALITY__PS > 5)\n                if(doneNP) {\n                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                    doneN = abs(lumaEndN) >= gradientScaled;\n                    doneP = abs(lumaEndP) >= gradientScaled;\n                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;\n                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;\n                    doneNP = (!doneN) || (!doneP);\n                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;\n                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;\n/*--------------------------------------------------------------------------*/\n                    #if (FXAA_QUALITY__PS > 6)\n                    if(doneNP) {\n                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                        doneN = abs(lumaEndN) >= gradientScaled;\n                        doneP = abs(lumaEndP) >= gradientScaled;\n                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;\n                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;\n                        doneNP = (!doneN) || (!doneP);\n                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;\n                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;\n/*--------------------------------------------------------------------------*/\n                        #if (FXAA_QUALITY__PS > 7)\n                        if(doneNP) {\n                            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                            doneN = abs(lumaEndN) >= gradientScaled;\n                            doneP = abs(lumaEndP) >= gradientScaled;\n                            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;\n                            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;\n                            doneNP = (!doneN) || (!doneP);\n                            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;\n                            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;\n/*--------------------------------------------------------------------------*/\n    #if (FXAA_QUALITY__PS > 8)\n    if(doneNP) {\n        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n        doneN = abs(lumaEndN) >= gradientScaled;\n        doneP = abs(lumaEndP) >= gradientScaled;\n        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;\n        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;\n        doneNP = (!doneN) || (!doneP);\n        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;\n        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;\n/*--------------------------------------------------------------------------*/\n        #if (FXAA_QUALITY__PS > 9)\n        if(doneNP) {\n            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n            doneN = abs(lumaEndN) >= gradientScaled;\n            doneP = abs(lumaEndP) >= gradientScaled;\n            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;\n            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;\n            doneNP = (!doneN) || (!doneP);\n            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;\n            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;\n/*--------------------------------------------------------------------------*/\n            #if (FXAA_QUALITY__PS > 10)\n            if(doneNP) {\n                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                doneN = abs(lumaEndN) >= gradientScaled;\n                doneP = abs(lumaEndP) >= gradientScaled;\n                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;\n                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;\n                doneNP = (!doneN) || (!doneP);\n                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;\n                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;\n/*--------------------------------------------------------------------------*/\n                #if (FXAA_QUALITY__PS > 11)\n                if(doneNP) {\n                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                    doneN = abs(lumaEndN) >= gradientScaled;\n                    doneP = abs(lumaEndP) >= gradientScaled;\n                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;\n                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;\n                    doneNP = (!doneN) || (!doneP);\n                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;\n                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;\n/*--------------------------------------------------------------------------*/\n                    #if (FXAA_QUALITY__PS > 12)\n                    if(doneNP) {\n                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                        doneN = abs(lumaEndN) >= gradientScaled;\n                        doneP = abs(lumaEndP) >= gradientScaled;\n                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;\n                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;\n                        doneNP = (!doneN) || (!doneP);\n                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;\n                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;\n/*--------------------------------------------------------------------------*/\n                    }\n                    #endif\n/*--------------------------------------------------------------------------*/\n                }\n                #endif\n/*--------------------------------------------------------------------------*/\n            }\n            #endif\n/*--------------------------------------------------------------------------*/\n        }\n        #endif\n/*--------------------------------------------------------------------------*/\n    }\n    #endif\n/*--------------------------------------------------------------------------*/\n                        }\n                        #endif\n/*--------------------------------------------------------------------------*/\n                    }\n                    #endif\n/*--------------------------------------------------------------------------*/\n                }\n                #endif\n/*--------------------------------------------------------------------------*/\n            }\n            #endif\n/*--------------------------------------------------------------------------*/\n        }\n        #endif\n/*--------------------------------------------------------------------------*/\n    }\n/*--------------------------------------------------------------------------*/\n    FxaaFloat dstN = posM.x - posN.x;\n    FxaaFloat dstP = posP.x - posM.x;\n    if(!horzSpan) dstN = posM.y - posN.y;\n    if(!horzSpan) dstP = posP.y - posM.y;\n/*--------------------------------------------------------------------------*/\n    FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;\n    FxaaFloat spanLength = (dstP + dstN);\n    FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;\n    FxaaFloat spanLengthRcp = 1.0/spanLength;\n/*--------------------------------------------------------------------------*/\n    FxaaBool directionN = dstN < dstP;\n    FxaaFloat dst = min(dstN, dstP);\n    FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;\n    FxaaFloat subpixG = subpixF * subpixF;\n    FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;\n    FxaaFloat subpixH = subpixG * fxaaQualitySubpix;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;\n    FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);\n    if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;\n    if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;\n    #if (FXAA_DISCARD == 1)\n        return FxaaTexTop(tex, posM);\n    #else\n        return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);\n    #endif\n}\n/*==========================================================================*/\n#endif\n\n\n\n\n/*============================================================================\n\n                         FXAA3 CONSOLE - PC VERSION\n                         \n------------------------------------------------------------------------------\nInstead of using this on PC, I'd suggest just using FXAA Quality with\n    #define FXAA_QUALITY__PRESET 10\nOr \n    #define FXAA_QUALITY__PRESET 20\nEither are higher qualilty and almost as fast as this on modern PC GPUs.\n============================================================================*/\n#if (FXAA_PC_CONSOLE == 1)\n/*--------------------------------------------------------------------------*/\nFxaaFloat4 FxaaPixelShader(\n    // See FXAA Quality FxaaPixelShader() source for docs on Inputs!\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));\n    FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));\n    FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));\n    FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));\n/*--------------------------------------------------------------------------*/\n    FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        FxaaFloat lumaM = rgbyM.w;\n    #else\n        FxaaFloat lumaM = rgbyM.y;\n    #endif\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);\n    lumaNe += 1.0/384.0;\n    FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);\n    FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);\n    FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat lumaMinM = min(lumaMin, lumaM);\n    FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);\n    FxaaFloat lumaMaxM = max(lumaMax, lumaM);\n    FxaaFloat dirSwMinusNe = lumaSw - lumaNe;\n    FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;\n    FxaaFloat dirSeMinusNw = lumaSe - lumaNw;\n    if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat2 dir;\n    dir.x = dirSwMinusNe + dirSeMinusNw;\n    dir.y = dirSwMinusNe - dirSeMinusNw;\n/*--------------------------------------------------------------------------*/\n    FxaaFloat2 dir1 = normalize(dir.xy);\n    FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);\n    FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;\n    FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);\n    FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);\n/*--------------------------------------------------------------------------*/\n    FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;\n    FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);\n/*--------------------------------------------------------------------------*/\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);\n    #else\n        FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);\n    #endif\n    if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;\n    return rgbyB; }\n/*==========================================================================*/\n#endif\n\n\n\n/*============================================================================\n\n                      FXAA3 CONSOLE - 360 PIXEL SHADER \n\n------------------------------------------------------------------------------\nThis optimized version thanks to suggestions from Andy Luedke.\nShould be fully tex bound in all cases.\nAs of the FXAA 3.11 release, I have still not tested this code,\nhowever I fixed a bug which was in both FXAA 3.9 and FXAA 3.10.\nAnd note this is replacing the old unoptimized version.\nIf it does not work, please let me know so I can fix it.\n============================================================================*/\n#if (FXAA_360 == 1)\n/*--------------------------------------------------------------------------*/\n[reduceTempRegUsage(4)]\nfloat4 FxaaPixelShader(\n    // See FXAA Quality FxaaPixelShader() source for docs on Inputs!\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n/*--------------------------------------------------------------------------*/\n    float4 lumaNwNeSwSe;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        asm { \n            tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX =  0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY =  0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX =  0.5, OffsetY =  0.5, UseComputedLOD=false\n        };\n    #else\n        asm { \n            tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX =  0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY =  0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX =  0.5, OffsetY =  0.5, UseComputedLOD=false\n        };\n    #endif\n/*--------------------------------------------------------------------------*/\n    lumaNwNeSwSe.y += 1.0/384.0;\n    float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);\n    float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);\n    float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);\n    float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);\n/*--------------------------------------------------------------------------*/\n    float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        float lumaMinM = min(lumaMin, rgbyM.w);\n        float lumaMaxM = max(lumaMax, rgbyM.w);\n    #else\n        float lumaMinM = min(lumaMin, rgbyM.y);\n        float lumaMaxM = max(lumaMax, rgbyM.y);\n    #endif        \n    if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;\n/*--------------------------------------------------------------------------*/\n    float2 dir;\n    dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);\n    dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);\n    dir = normalize(dir);\n/*--------------------------------------------------------------------------*/\n    float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;\n/*--------------------------------------------------------------------------*/\n    float4 dir2;\n    float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;\n    dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);\n    dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;\n/*--------------------------------------------------------------------------*/\n    float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));\n    float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));\n    float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));\n    float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));\n/*--------------------------------------------------------------------------*/\n    float4 rgbyA = rgbyN1 + rgbyP1;\n    float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;\n/*--------------------------------------------------------------------------*/\n    float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; \n    rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; \n    return rgbyR; }\n/*==========================================================================*/\n#endif\n\n\n\n/*============================================================================\n\n         FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)\n\n==============================================================================\nThe code below does not exactly match the assembly.\nI have a feeling that 12 cycles is possible, but was not able to get there.\nMight have to increase register count to get full performance.\nNote this shader does not use perspective interpolation.\n\nUse the following cgc options,\n\n  --fenable-bx2 --fastmath --fastprecision --nofloatbindings\n\n------------------------------------------------------------------------------\n                             NVSHADERPERF OUTPUT\n------------------------------------------------------------------------------\nFor reference and to aid in debug, output of NVShaderPerf should match this,\n\nShader to schedule:\n  0: texpkb h0.w(TRUE), v5.zyxx, #0\n  2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x\n  4: texpkb h0.w(TRUE), v5.xwxx, #0\n  6: addh h0.z(TRUE), -h2, h0.w\n  7: texpkb h1.w(TRUE), v5, #0\n  9: addh h0.x(TRUE), h0.z, -h1.w\n 10: addh h3.w(TRUE), h0.z, h1\n 11: texpkb h2.w(TRUE), v5.zwzz, #0\n 13: addh h0.z(TRUE), h3.w, -h2.w\n 14: addh h0.x(TRUE), h2.w, h0\n 15: nrmh h1.xz(TRUE), h0_n\n 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|\n 17: maxh h4.w(TRUE), h0, h1\n 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n\n 19: movr r1.zw(TRUE), v4.xxxy\n 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww\n 22: minh h5.w(TRUE), h0, h1\n 23: texpkb h0(TRUE), r2.xzxx, #0\n 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1\n 27: maxh h4.x(TRUE), h2.z, h2.w\n 28: texpkb h1(TRUE), r0.zwzz, #0\n 30: addh_d2 h1(TRUE), h0, h1\n 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz\n 33: texpkb h0(TRUE), r0, #0\n 35: minh h4.z(TRUE), h2, h2.w\n 36: fenct TRUE\n 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz\n 39: texpkb h2(TRUE), r1, #0\n 41: addh_d2 h0(TRUE), h0, h2\n 42: maxh h2.w(TRUE), h4, h4.x\n 43: minh h2.x(TRUE), h5.w, h4.z\n 44: addh_d2 h0(TRUE), h0, h1\n 45: slth h2.x(TRUE), h0.w, h2\n 46: sgth h2.w(TRUE), h0, h2\n 47: movh h0(TRUE), h0\n 48: addx.c0 rc(TRUE), h2, h2.w\n 49: movh h0(c0.NE.x), h1\n\nIPU0 ------ Simplified schedule: --------\nPass |  Unit  |  uOp |  PC:  Op\n-----+--------+------+-------------------------\n   1 | SCT0/1 |  mov |   0:  TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;\n     |    TEX |  txl |   0:  TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;\n     |   SCB1 |  add |   2:  ADDh h2.z, h0.--w-, const.--x-;\n     |        |      |\n   2 | SCT0/1 |  mov |   4:  TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;\n     |    TEX |  txl |   4:  TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;\n     |   SCB1 |  add |   6:  ADDh h0.z,-h2, h0.--w-;\n     |        |      |\n   3 | SCT0/1 |  mov |   7:  TXLr h1.w, g[TEX1], const.xxxx, TEX0;\n     |    TEX |  txl |   7:  TXLr h1.w, g[TEX1], const.xxxx, TEX0;\n     |   SCB0 |  add |   9:  ADDh h0.x, h0.z---,-h1.w---;\n     |   SCB1 |  add |  10:  ADDh h3.w, h0.---z, h1;\n     |        |      |\n   4 | SCT0/1 |  mov |  11:  TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;\n     |    TEX |  txl |  11:  TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;\n     |   SCB0 |  add |  14:  ADDh h0.x, h2.w---, h0;\n     |   SCB1 |  add |  13:  ADDh h0.z, h3.--w-,-h2.--w-;\n     |        |      |\n   5 |   SCT1 |  mov |  15:  NRMh h1.xz, h0;\n     |    SRB |  nrm |  15:  NRMh h1.xz, h0;\n     |   SCB0 |  min |  16:  MINh*8 h0.x, |h1|, |h1.z---|;\n     |   SCB1 |  max |  17:  MAXh h4.w, h0, h1;\n     |        |      |\n   6 |   SCT0 |  div |  18:  DIVx h2.xy, h1.xz--, h0;\n     |   SCT1 |  mov |  19:  MOVr r1.zw, g[TEX0].--xy;\n     |   SCB0 |  mad |  20:  MADr r2.xz,-h1, const.z-w-, r1.z-w-;\n     |   SCB1 |  min |  22:  MINh h5.w, h0, h1;\n     |        |      |\n   7 | SCT0/1 |  mov |  23:  TXLr h0, r2.xzxx, const.xxxx, TEX0;\n     |    TEX |  txl |  23:  TXLr h0, r2.xzxx, const.xxxx, TEX0;\n     |   SCB0 |  max |  27:  MAXh h4.x, h2.z---, h2.w---;\n     |   SCB1 |  mad |  25:  MADr r0.zw, h1.--xz, const, r1;\n     |        |      |\n   8 | SCT0/1 |  mov |  28:  TXLr h1, r0.zwzz, const.xxxx, TEX0;\n     |    TEX |  txl |  28:  TXLr h1, r0.zwzz, const.xxxx, TEX0;\n     | SCB0/1 |  add |  30:  ADDh/2 h1, h0, h1;\n     |        |      |\n   9 |   SCT0 |  mad |  31:  MADr r0.xy,-h2, const.xy--, r1.zw--;\n     |   SCT1 |  mov |  33:  TXLr h0, r0, const.zzzz, TEX0;\n     |    TEX |  txl |  33:  TXLr h0, r0, const.zzzz, TEX0;\n     |   SCB1 |  min |  35:  MINh h4.z, h2, h2.--w-;\n     |        |      |\n  10 |   SCT0 |  mad |  37:  MADr r1.xy, h2, const.xy--, r1.zw--;\n     |   SCT1 |  mov |  39:  TXLr h2, r1, const.zzzz, TEX0;\n     |    TEX |  txl |  39:  TXLr h2, r1, const.zzzz, TEX0;\n     | SCB0/1 |  add |  41:  ADDh/2 h0, h0, h2;\n     |        |      |\n  11 |   SCT0 |  min |  43:  MINh h2.x, h5.w---, h4.z---;\n     |   SCT1 |  max |  42:  MAXh h2.w, h4, h4.---x;\n     | SCB0/1 |  add |  44:  ADDh/2 h0, h0, h1;\n     |        |      |\n  12 |   SCT0 |  set |  45:  SLTh h2.x, h0.w---, h2;\n     |   SCT1 |  set |  46:  SGTh h2.w, h0, h2;\n     | SCB0/1 |  mul |  47:  MOVh h0, h0;\n     |        |      |\n  13 |   SCT0 |  mad |  48:  ADDxc0_s rc, h2, h2.w---;\n     | SCB0/1 |  mul |  49:  MOVh h0(NE0.xxxx), h1;\n \nPass   SCT  TEX  SCB\n  1:   0% 100%  25%\n  2:   0% 100%  25%\n  3:   0% 100%  50%\n  4:   0% 100%  50%\n  5:   0%   0%  50%\n  6: 100%   0%  75%\n  7:   0% 100%  75%\n  8:   0% 100% 100%\n  9:   0% 100%  25%\n 10:   0% 100% 100%\n 11:  50%   0% 100%\n 12:  50%   0% 100%\n 13:  25%   0% 100%\n\nMEAN:  17%  61%  67%\n\nPass   SCT0  SCT1   TEX  SCB0  SCB1\n  1:    0%    0%  100%    0%  100%\n  2:    0%    0%  100%    0%  100%\n  3:    0%    0%  100%  100%  100%\n  4:    0%    0%  100%  100%  100%\n  5:    0%    0%    0%  100%  100%\n  6:  100%  100%    0%  100%  100%\n  7:    0%    0%  100%  100%  100%\n  8:    0%    0%  100%  100%  100%\n  9:    0%    0%  100%    0%  100%\n 10:    0%    0%  100%  100%  100%\n 11:  100%  100%    0%  100%  100%\n 12:  100%  100%    0%  100%  100%\n 13:  100%    0%    0%  100%  100%\n\nMEAN:   30%   23%   61%   76%  100%\nFragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5\nResults 13 cycles, 3 r regs, 923,076,923 pixels/s\n============================================================================*/\n#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)\n/*--------------------------------------------------------------------------*/\n#pragma regcount 7\n#pragma disablepc all\n#pragma option O3\n#pragma option OutColorPrec=fp16\n#pragma texformat default RGBA8\n/*==========================================================================*/\nhalf4 FxaaPixelShader(\n    // See FXAA Quality FxaaPixelShader() source for docs on Inputs!\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n/*--------------------------------------------------------------------------*/\n// (1)\n    half4 dir;\n    half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        lumaNe.w += half(1.0/512.0);\n        dir.x = -lumaNe.w;\n        dir.z = -lumaNe.w;\n    #else\n        lumaNe.y += half(1.0/512.0);\n        dir.x = -lumaNe.y;\n        dir.z = -lumaNe.y;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (2)\n    half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x += lumaSw.w;\n        dir.z += lumaSw.w;\n    #else\n        dir.x += lumaSw.y;\n        dir.z += lumaSw.y;\n    #endif        \n/*--------------------------------------------------------------------------*/\n// (3)\n    half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x -= lumaNw.w;\n        dir.z += lumaNw.w;\n    #else\n        dir.x -= lumaNw.y;\n        dir.z += lumaNw.y;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (4)\n    half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x += lumaSe.w;\n        dir.z -= lumaSe.w;\n    #else\n        dir.x += lumaSe.y;\n        dir.z -= lumaSe.y;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (5)\n    half4 dir1_pos;\n    dir1_pos.xy = normalize(dir.xyz).xz;\n    half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);\n/*--------------------------------------------------------------------------*/\n// (6)\n    half4 dir2_pos;\n    dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));\n    dir1_pos.zw = pos.xy;\n    dir2_pos.zw = pos.xy;\n    half4 temp1N;\n    temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n/*--------------------------------------------------------------------------*/\n// (7)\n    temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));\n    half4 rgby1;\n    rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n/*--------------------------------------------------------------------------*/\n// (8)\n    rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));\n    rgby1 = (temp1N + rgby1) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (9)\n    half4 temp2N;\n    temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));\n/*--------------------------------------------------------------------------*/\n// (10)\n    half4 rgby2;\n    rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));\n    rgby2 = (temp2N + rgby2) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (11)\n    // compilier moves these scalar ops up to other cycles\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));\n        half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));\n    #else\n        half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));\n        half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));\n    #endif        \n    rgby2 = (rgby2 + rgby1) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (12)\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        bool twoTapLt = rgby2.w < lumaMin;\n        bool twoTapGt = rgby2.w > lumaMax;\n    #else\n        bool twoTapLt = rgby2.y < lumaMin;\n        bool twoTapGt = rgby2.y > lumaMax;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (13)\n    if(twoTapLt || twoTapGt) rgby2 = rgby1;\n/*--------------------------------------------------------------------------*/\n    return rgby2; }\n/*==========================================================================*/\n#endif\n\n\n\n/*============================================================================\n\n       FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)\n\n==============================================================================\nThe code mostly matches the assembly.\nI have a feeling that 14 cycles is possible, but was not able to get there.\nMight have to increase register count to get full performance.\nNote this shader does not use perspective interpolation.\n\nUse the following cgc options,\n\n --fenable-bx2 --fastmath --fastprecision --nofloatbindings\n\nUse of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks).\nWill look at fixing this for FXAA 3.12.\n------------------------------------------------------------------------------\n                             NVSHADERPERF OUTPUT\n------------------------------------------------------------------------------\nFor reference and to aid in debug, output of NVShaderPerf should match this,\n\nShader to schedule:\n  0: texpkb h0.w(TRUE), v5.zyxx, #0\n  2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x\n  4: texpkb h1.w(TRUE), v5.xwxx, #0\n  6: addh h0.x(TRUE), h1.w, -h2.y\n  7: texpkb h2.w(TRUE), v5.zwzz, #0\n  9: minh h4.w(TRUE), h2.y, h2\n 10: maxh h5.x(TRUE), h2.y, h2.w\n 11: texpkb h0.w(TRUE), v5, #0\n 13: addh h3.w(TRUE), -h0, h0.x\n 14: addh h0.x(TRUE), h0.w, h0\n 15: addh h0.z(TRUE), -h2.w, h0.x\n 16: addh h0.x(TRUE), h2.w, h3.w\n 17: minh h5.y(TRUE), h0.w, h1.w\n 18: nrmh h2.xz(TRUE), h0_n\n 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|\n 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w\n 21: movr r1.zw(TRUE), v4.xxxy\n 22: maxh h2.w(TRUE), h0, h1\n 23: fenct TRUE\n 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz\n 26: texpkb h0(TRUE), r0, #0\n 28: maxh h5.x(TRUE), h2.w, h5\n 29: minh h5.w(TRUE), h5.y, h4\n 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz\n 32: texpkb h2(TRUE), r1, #0\n 34: addh_d2 h2(TRUE), h0, h2\n 35: texpkb h1(TRUE), v4, #0\n 37: maxh h5.y(TRUE), h5.x, h1.w\n 38: minh h4.w(TRUE), h1, h5\n 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz\n 41: texpkb h0(TRUE), r0, #0\n 43: addh_m8 h5.z(TRUE), h5.y, -h4.w\n 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz\n 46: texpkb h3(TRUE), r2, #0\n 48: addh_d2 h0(TRUE), h0, h3\n 49: addh_d2 h3(TRUE), h0, h2\n 50: movh h0(TRUE), h3\n 51: slth h3.x(TRUE), h3.w, h5.w\n 52: sgth h3.w(TRUE), h3, h5.x\n 53: addx.c0 rc(TRUE), h3.x, h3\n 54: slth.c0 rc(TRUE), h5.z, h5\n 55: movh h0(c0.NE.w), h2\n 56: movh h0(c0.NE.x), h1\n\nIPU0 ------ Simplified schedule: --------\nPass |  Unit  |  uOp |  PC:  Op\n-----+--------+------+-------------------------\n   1 | SCT0/1 |  mov |   0:  TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;\n     |    TEX |  txl |   0:  TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;\n     |   SCB0 |  add |   2:  ADDh h2.y, h0.-w--, const.-x--;\n     |        |      |\n   2 | SCT0/1 |  mov |   4:  TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;\n     |    TEX |  txl |   4:  TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;\n     |   SCB0 |  add |   6:  ADDh h0.x, h1.w---,-h2.y---;\n     |        |      |\n   3 | SCT0/1 |  mov |   7:  TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;\n     |    TEX |  txl |   7:  TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;\n     |   SCB0 |  max |  10:  MAXh h5.x, h2.y---, h2.w---;\n     |   SCB1 |  min |   9:  MINh h4.w, h2.---y, h2;\n     |        |      |\n   4 | SCT0/1 |  mov |  11:  TXLr h0.w, g[TEX1], const.xxxx, TEX0;\n     |    TEX |  txl |  11:  TXLr h0.w, g[TEX1], const.xxxx, TEX0;\n     |   SCB0 |  add |  14:  ADDh h0.x, h0.w---, h0;\n     |   SCB1 |  add |  13:  ADDh h3.w,-h0, h0.---x;\n     |        |      |\n   5 |   SCT0 |  mad |  16:  ADDh h0.x, h2.w---, h3.w---;\n     |   SCT1 |  mad |  15:  ADDh h0.z,-h2.--w-, h0.--x-;\n     |   SCB0 |  min |  17:  MINh h5.y, h0.-w--, h1.-w--;\n     |        |      |\n   6 |   SCT1 |  mov |  18:  NRMh h2.xz, h0;\n     |    SRB |  nrm |  18:  NRMh h2.xz, h0;\n     |   SCB1 |  min |  19:  MINh*8 h2.w, |h2.---x|, |h2.---z|;\n     |        |      |\n   7 |   SCT0 |  div |  20:  DIVx h4.xy, h2.xz--, h2.ww--;\n     |   SCT1 |  mov |  21:  MOVr r1.zw, g[TEX0].--xy;\n     |   SCB1 |  max |  22:  MAXh h2.w, h0, h1;\n     |        |      |\n   8 |   SCT0 |  mad |  24:  MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;\n     |   SCT1 |  mov |  26:  TXLr h0, r0, const.xxxx, TEX0;\n     |    TEX |  txl |  26:  TXLr h0, r0, const.xxxx, TEX0;\n     |   SCB0 |  max |  28:  MAXh h5.x, h2.w---, h5;\n     |   SCB1 |  min |  29:  MINh h5.w, h5.---y, h4;\n     |        |      |\n   9 |   SCT0 |  mad |  30:  MADr r1.xy, h2.xz--, const.zw--, r1.zw--;\n     |   SCT1 |  mov |  32:  TXLr h2, r1, const.xxxx, TEX0;\n     |    TEX |  txl |  32:  TXLr h2, r1, const.xxxx, TEX0;\n     | SCB0/1 |  add |  34:  ADDh/2 h2, h0, h2;\n     |        |      |\n  10 | SCT0/1 |  mov |  35:  TXLr h1, g[TEX0], const.xxxx, TEX0;\n     |    TEX |  txl |  35:  TXLr h1, g[TEX0], const.xxxx, TEX0;\n     |   SCB0 |  max |  37:  MAXh h5.y, h5.-x--, h1.-w--;\n     |   SCB1 |  min |  38:  MINh h4.w, h1, h5;\n     |        |      |\n  11 |   SCT0 |  mad |  39:  MADr r0.xy,-h4, const.xy--, r1.zw--;\n     |   SCT1 |  mov |  41:  TXLr h0, r0, const.zzzz, TEX0;\n     |    TEX |  txl |  41:  TXLr h0, r0, const.zzzz, TEX0;\n     |   SCB0 |  mad |  44:  MADr r2.xy, h4, const.xy--, r1.zw--;\n     |   SCB1 |  add |  43:  ADDh*8 h5.z, h5.--y-,-h4.--w-;\n     |        |      |\n  12 | SCT0/1 |  mov |  46:  TXLr h3, r2, const.xxxx, TEX0;\n     |    TEX |  txl |  46:  TXLr h3, r2, const.xxxx, TEX0;\n     | SCB0/1 |  add |  48:  ADDh/2 h0, h0, h3;\n     |        |      |\n  13 | SCT0/1 |  mad |  49:  ADDh/2 h3, h0, h2;\n     | SCB0/1 |  mul |  50:  MOVh h0, h3;\n     |        |      |\n  14 |   SCT0 |  set |  51:  SLTh h3.x, h3.w---, h5.w---;\n     |   SCT1 |  set |  52:  SGTh h3.w, h3, h5.---x;\n     |   SCB0 |  set |  54:  SLThc0 rc, h5.z---, h5;\n     |   SCB1 |  add |  53:  ADDxc0_s rc, h3.---x, h3;\n     |        |      |\n  15 | SCT0/1 |  mul |  55:  MOVh h0(NE0.wwww), h2;\n     | SCB0/1 |  mul |  56:  MOVh h0(NE0.xxxx), h1;\n \nPass   SCT  TEX  SCB\n  1:   0% 100%  25%\n  2:   0% 100%  25%\n  3:   0% 100%  50%\n  4:   0% 100%  50%\n  5:  50%   0%  25%\n  6:   0%   0%  25%\n  7: 100%   0%  25%\n  8:   0% 100%  50%\n  9:   0% 100% 100%\n 10:   0% 100%  50%\n 11:   0% 100%  75%\n 12:   0% 100% 100%\n 13: 100%   0% 100%\n 14:  50%   0%  50%\n 15: 100%   0% 100%\n\nMEAN:  26%  60%  56%\n\nPass   SCT0  SCT1   TEX  SCB0  SCB1\n  1:    0%    0%  100%  100%    0%\n  2:    0%    0%  100%  100%    0%\n  3:    0%    0%  100%  100%  100%\n  4:    0%    0%  100%  100%  100%\n  5:  100%  100%    0%  100%    0%\n  6:    0%    0%    0%    0%  100%\n  7:  100%  100%    0%    0%  100%\n  8:    0%    0%  100%  100%  100%\n  9:    0%    0%  100%  100%  100%\n 10:    0%    0%  100%  100%  100%\n 11:    0%    0%  100%  100%  100%\n 12:    0%    0%  100%  100%  100%\n 13:  100%  100%    0%  100%  100%\n 14:  100%  100%    0%  100%  100%\n 15:  100%  100%    0%  100%  100%\n\nMEAN:   33%   33%   60%   86%   80%\nFragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5\nResults 15 cycles, 3 r regs, 800,000,000 pixels/s\n============================================================================*/\n#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)\n/*--------------------------------------------------------------------------*/\n#pragma regcount 7\n#pragma disablepc all\n#pragma option O2\n#pragma option OutColorPrec=fp16\n#pragma texformat default RGBA8\n/*==========================================================================*/\nhalf4 FxaaPixelShader(\n    // See FXAA Quality FxaaPixelShader() source for docs on Inputs!\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n/*--------------------------------------------------------------------------*/\n// (1)\n    half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaNe = rgbyNe.w + half(1.0/512.0);\n    #else\n        half lumaNe = rgbyNe.y + half(1.0/512.0);\n    #endif\n/*--------------------------------------------------------------------------*/\n// (2)\n    half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaSwNegNe = lumaSw.w - lumaNe;\n    #else\n        half lumaSwNegNe = lumaSw.y - lumaNe;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (3)\n    half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);\n        half lumaMinNwSw = min(lumaNw.w, lumaSw.w);\n    #else\n        half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);\n        half lumaMinNwSw = min(lumaNw.y, lumaSw.y);\n    #endif\n/*--------------------------------------------------------------------------*/\n// (4)\n    half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half dirZ =  lumaNw.w + lumaSwNegNe;\n        half dirX = -lumaNw.w + lumaSwNegNe;\n    #else\n        half dirZ =  lumaNw.y + lumaSwNegNe;\n        half dirX = -lumaNw.y + lumaSwNegNe;\n    #endif\n/*--------------------------------------------------------------------------*/\n// (5)\n    half3 dir;\n    dir.y = 0.0;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x =  lumaSe.w + dirX;\n        dir.z = -lumaSe.w + dirZ;\n        half lumaMinNeSe = min(lumaNe, lumaSe.w);\n    #else\n        dir.x =  lumaSe.y + dirX;\n        dir.z = -lumaSe.y + dirZ;\n        half lumaMinNeSe = min(lumaNe, lumaSe.y);\n    #endif\n/*--------------------------------------------------------------------------*/\n// (6)\n    half4 dir1_pos;\n    dir1_pos.xy = normalize(dir).xz;\n    half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);\n/*--------------------------------------------------------------------------*/\n// (7)\n    half4 dir2_pos;\n    dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));\n    dir1_pos.zw = pos.xy;\n    dir2_pos.zw = pos.xy;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxNeSe = max(lumaNe, lumaSe.w);\n    #else\n        half lumaMaxNeSe = max(lumaNe, lumaSe.y);\n    #endif\n/*--------------------------------------------------------------------------*/\n// (8)\n    half4 temp1N;\n    temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));\n    half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);\n    half lumaMin = min(lumaMinNwSw, lumaMinNeSe);\n/*--------------------------------------------------------------------------*/\n// (9)\n    half4 rgby1;\n    rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));\n    rgby1 = (temp1N + rgby1) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (10)\n    half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxM = max(lumaMax, rgbyM.w);\n        half lumaMinM = min(lumaMin, rgbyM.w);\n    #else\n        half lumaMaxM = max(lumaMax, rgbyM.y);\n        half lumaMinM = min(lumaMin, rgbyM.y);\n    #endif\n/*--------------------------------------------------------------------------*/\n// (11)\n    half4 temp2N;\n    temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));\n    half4 rgby2;\n    rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD;\n/*--------------------------------------------------------------------------*/\n// (12)\n    rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));\n    rgby2 = (temp2N + rgby2) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (13)\n    rgby2 = (rgby2 + rgby1) * 0.5;\n/*--------------------------------------------------------------------------*/\n// (14)\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        bool twoTapLt = rgby2.w < lumaMin;\n        bool twoTapGt = rgby2.w > lumaMax;\n    #else\n        bool twoTapLt = rgby2.y < lumaMin;\n        bool twoTapGt = rgby2.y > lumaMax;\n    #endif\n    bool earlyExit = lumaRangeM < lumaMax;\n    bool twoTap = twoTapLt || twoTapGt;\n/*--------------------------------------------------------------------------*/\n// (15)\n    if(twoTap) rgby2 = rgby1;\n    if(earlyExit) rgby2 = rgbyM;\n/*--------------------------------------------------------------------------*/\n    return rgby2; }\n/*==========================================================================*/\n#endif\n"
  },
  {
    "path": "src/antialias/fxaa3_11_preprocessed.shaderlib",
    "content": "float FxaaLuma(vec4 rgba) { return rgba.y; }\nvec4 FxaaPixelShader(\n    vec2 pos\n    ,sampler2D tex\n    ,vec2 fxaaQualityRcpFrame\n    ,float fxaaQualitySubpix\n    ,float fxaaQualityEdgeThreshold\n    ,float fxaaQualityEdgeThresholdMin\n) {\n    vec2 posM;\n    posM.x = pos.x;\n    posM.y = pos.y;\n    vec4 rgbyM = texture2D(tex, posM, 0.0);\n    float lumaS = FxaaLuma(texture2D(tex, posM + (vec2( 0.0, 1.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaE = FxaaLuma(texture2D(tex, posM + (vec2( 1.0, 0.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaN = FxaaLuma(texture2D(tex, posM + (vec2( 0.0,-1.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaW = FxaaLuma(texture2D(tex, posM + (vec2(-1.0, 0.0) * fxaaQualityRcpFrame.xy), 0.0));\n\n    float maxSM = max(lumaS, rgbyM.y);\n    float minSM = min(lumaS, rgbyM.y);\n    float maxESM = max(lumaE, maxSM);\n    float minESM = min(lumaE, minSM);\n    float maxWN = max(lumaN, lumaW);\n    float minWN = min(lumaN, lumaW);\n    float rangeMax = max(maxWN, maxESM);\n    float rangeMin = min(minWN, minESM);\n    float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;\n    float range = rangeMax - rangeMin;\n    float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);\n    bool earlyExit = range < rangeMaxClamped;\n    if(earlyExit) return rgbyM;\n    float lumaNW = FxaaLuma(texture2D(tex, posM + (vec2(-1.0,-1.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaSE = FxaaLuma(texture2D(tex, posM + (vec2( 1.0, 1.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaNE = FxaaLuma(texture2D(tex, posM + (vec2( 1.0,-1.0) * fxaaQualityRcpFrame.xy), 0.0));\n    float lumaSW = FxaaLuma(texture2D(tex, posM + (vec2(-1.0, 1.0) * fxaaQualityRcpFrame.xy), 0.0));\n\n    float lumaNS = lumaN + lumaS;\n    float lumaWE = lumaW + lumaE;\n    float subpixRcpRange = 1.0/range;\n    float subpixNSWE = lumaNS + lumaWE;\n    float edgeHorz1 = (-2.0 * rgbyM.y) + lumaNS;\n    float edgeVert1 = (-2.0 * rgbyM.y) + lumaWE;\n    float lumaNESE = lumaNE + lumaSE;\n    float lumaNWNE = lumaNW + lumaNE;\n    float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;\n    float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;\n    float lumaNWSW = lumaNW + lumaSW;\n    float lumaSWSE = lumaSW + lumaSE;\n    float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);\n    float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);\n    float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;\n    float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;\n    float edgeHorz = abs(edgeHorz3) + edgeHorz4;\n    float edgeVert = abs(edgeVert3) + edgeVert4;\n    float subpixNWSWNESE = lumaNWSW + lumaNESE;\n    float lengthSign = fxaaQualityRcpFrame.x;\n    bool horzSpan = edgeHorz >= edgeVert;\n    float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;\n    if(!horzSpan) lumaN = lumaW;\n    if(!horzSpan) lumaS = lumaE;\n    if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;\n    float subpixB = (subpixA * (1.0/12.0)) - rgbyM.y;\n    float gradientN = lumaN - rgbyM.y;\n    float gradientS = lumaS - rgbyM.y;\n    float lumaNN = lumaN + rgbyM.y;\n    float lumaSS = lumaS + rgbyM.y;\n    bool pairN = abs(gradientN) >= abs(gradientS);\n    float gradient = max(abs(gradientN), abs(gradientS));\n    if(pairN) lengthSign = -lengthSign;\n    float subpixC = clamp(abs(subpixB) * subpixRcpRange, 0.0, 1.0);\n    vec2 posB;\n    posB.x = posM.x;\n    posB.y = posM.y;\n    vec2 offNP;\n    offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n    offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n    if(!horzSpan) posB.x += lengthSign * 0.5;\n    if( horzSpan) posB.y += lengthSign * 0.5;\n    vec2 posN;\n    posN.x = posB.x - offNP.x * 1.0;\n    posN.y = posB.y - offNP.y * 1.0;\n    vec2 posP;\n    posP.x = posB.x + offNP.x * 1.0;\n    posP.y = posB.y + offNP.y * 1.0;\n    float subpixD = ((-2.0)*subpixC) + 3.0;\n    float lumaEndN = FxaaLuma(texture2D(tex, posN, 0.0));\n    float subpixE = subpixC * subpixC;\n    float lumaEndP = FxaaLuma(texture2D(tex, posP, 0.0));\n    if(!pairN) lumaNN = lumaSS;\n    float gradientScaled = gradient * 1.0/4.0;\n    float lumaMM = rgbyM.y - lumaNN * 0.5;\n    float subpixF = subpixD * subpixE;\n    bool lumaMLTZero = lumaMM < 0.0;\n    lumaEndN -= lumaNN * 0.5;\n    lumaEndP -= lumaNN * 0.5;\n    bool doneN = abs(lumaEndN) >= gradientScaled;\n    bool doneP = abs(lumaEndP) >= gradientScaled;\n    if(!doneN) posN.x -= offNP.x * 1.5;\n    if(!doneN) posN.y -= offNP.y * 1.5;\n    bool doneNP = (!doneN) || (!doneP);\n    if(!doneP) posP.x += offNP.x * 1.5;\n    if(!doneP) posP.y += offNP.y * 1.5;\n    if(doneNP) {\n        if(!doneN) lumaEndN = FxaaLuma(texture2D(tex, posN.xy, 0.0));\n        if(!doneP) lumaEndP = FxaaLuma(texture2D(tex, posP.xy, 0.0));\n        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n        doneN = abs(lumaEndN) >= gradientScaled;\n        doneP = abs(lumaEndP) >= gradientScaled;\n        if(!doneN) posN.x -= offNP.x * 2.0;\n        if(!doneN) posN.y -= offNP.y * 2.0;\n        doneNP = (!doneN) || (!doneP);\n        if(!doneP) posP.x += offNP.x * 2.0;\n        if(!doneP) posP.y += offNP.y * 2.0;\n\n        if(doneNP) {\n            if(!doneN) lumaEndN = FxaaLuma(texture2D(tex, posN.xy, 0.0));\n            if(!doneP) lumaEndP = FxaaLuma(texture2D(tex, posP.xy, 0.0));\n            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n            doneN = abs(lumaEndN) >= gradientScaled;\n            doneP = abs(lumaEndP) >= gradientScaled;\n            if(!doneN) posN.x -= offNP.x * 4.0;\n            if(!doneN) posN.y -= offNP.y * 4.0;\n            doneNP = (!doneN) || (!doneP);\n            if(!doneP) posP.x += offNP.x * 4.0;\n            if(!doneP) posP.y += offNP.y * 4.0;\n\n            if(doneNP) {\n                if(!doneN) lumaEndN = FxaaLuma(texture2D(tex, posN.xy, 0.0));\n                if(!doneP) lumaEndP = FxaaLuma(texture2D(tex, posP.xy, 0.0));\n                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                doneN = abs(lumaEndN) >= gradientScaled;\n                doneP = abs(lumaEndP) >= gradientScaled;\n                if(!doneN) posN.x -= offNP.x * 12.0;\n                if(!doneN) posN.y -= offNP.y * 12.0;\n                doneNP = (!doneN) || (!doneP);\n                if(!doneP) posP.x += offNP.x * 12.0;\n                if(!doneP) posP.y += offNP.y * 12.0;\n            }\n\n        }\n\n    }\n    float dstN = posM.x - posN.x;\n    float dstP = posP.x - posM.x;\n    if(!horzSpan) dstN = posM.y - posN.y;\n    if(!horzSpan) dstP = posP.y - posM.y;\n    bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;\n    float spanLength = (dstP + dstN);\n    bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;\n    float spanLengthRcp = 1.0/spanLength;\n    bool directionN = dstN < dstP;\n    float dst = min(dstN, dstP);\n    bool goodSpan = directionN ? goodSpanN : goodSpanP;\n    float subpixG = subpixF * subpixF;\n    float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;\n    float subpixH = subpixG * fxaaQualitySubpix;\n    float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;\n    float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);\n    if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;\n    if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;\n    return vec4(texture2D(tex, posM, 0.0).xyz, rgbyM.y);\n\n}\n"
  },
  {
    "path": "src/antialias/fxaa3_11_stripped.shaderlib",
    "content": "#ifndef FXAA_PS3\n    #define FXAA_PS3 0\n#endif\n#ifndef FXAA_360\n    #define FXAA_360 0\n#endif\n#ifndef FXAA_360_OPT\n    #define FXAA_360_OPT 0\n#endif\n#ifndef FXAA_PC\n    #define FXAA_PC 1\n#endif\n#ifndef FXAA_PC_CONSOLE\n    #define FXAA_PC_CONSOLE 0\n#endif\n#ifndef FXAA_GLSL_120\n    #define FXAA_GLSL_120 0\n#endif\n#ifndef FXAA_GLSL_130\n    #define FXAA_GLSL_130 0\n#endif\n#ifndef FXAA_HLSL_3\n    #define FXAA_HLSL_3 0\n#endif\n#ifndef FXAA_HLSL_4\n    #define FXAA_HLSL_4 0\n#endif\n#ifndef FXAA_HLSL_5\n    #define FXAA_HLSL_5 0\n#endif\n#ifndef FXAA_GREEN_AS_LUMA\n    #define FXAA_GREEN_AS_LUMA 1\n#endif\n#ifndef FXAA_EARLY_EXIT\n    #define FXAA_EARLY_EXIT 1\n#endif\n#ifndef FXAA_DISCARD\n    #define FXAA_DISCARD 0\n#endif\n#ifndef FXAA_FAST_PIXEL_OFFSET\n    #ifdef GL_EXT_gpu_shader4\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifdef GL_NV_gpu_shader5\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifdef GL_ARB_gpu_shader5\n        #define FXAA_FAST_PIXEL_OFFSET 1\n    #endif\n    #ifndef FXAA_FAST_PIXEL_OFFSET\n        #define FXAA_FAST_PIXEL_OFFSET 0\n    #endif\n#endif\n#ifndef FXAA_GATHER4_ALPHA\n    #if (FXAA_HLSL_5 == 1)\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifdef GL_ARB_gpu_shader5\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifdef GL_NV_gpu_shader5\n        #define FXAA_GATHER4_ALPHA 1\n    #endif\n    #ifndef FXAA_GATHER4_ALPHA\n        #define FXAA_GATHER4_ALPHA 0\n    #endif\n#endif\n#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS\n    #if 1\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0\n    #endif\n    #if 0\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0\n    #endif\n    #if 0\n        #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0\n    #endif\n#endif\n#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD\n    #if 1\n        #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125\n    #else\n        #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25\n    #endif\n#endif\n#ifndef FXAA_QUALITY__PRESET\n    #define FXAA_QUALITY__PRESET 12\n#endif\n#if (FXAA_QUALITY__PRESET == 10)\n    #define FXAA_QUALITY__PS 3\n    #define FXAA_QUALITY__P0 1.5\n    #define FXAA_QUALITY__P1 3.0\n    #define FXAA_QUALITY__P2 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 11)\n    #define FXAA_QUALITY__PS 4\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 3.0\n    #define FXAA_QUALITY__P3 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 12)\n    #define FXAA_QUALITY__PS 5\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 4.0\n    #define FXAA_QUALITY__P4 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 13)\n    #define FXAA_QUALITY__PS 6\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 4.0\n    #define FXAA_QUALITY__P5 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 14)\n    #define FXAA_QUALITY__PS 7\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 4.0\n    #define FXAA_QUALITY__P6 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 15)\n    #define FXAA_QUALITY__PS 8\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 4.0\n    #define FXAA_QUALITY__P7 12.0\n#endif\n#if (FXAA_QUALITY__PRESET == 20)\n    #define FXAA_QUALITY__PS 3\n    #define FXAA_QUALITY__P0 1.5\n    #define FXAA_QUALITY__P1 2.0\n    #define FXAA_QUALITY__P2 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 21)\n    #define FXAA_QUALITY__PS 4\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 22)\n    #define FXAA_QUALITY__PS 5\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 23)\n    #define FXAA_QUALITY__PS 6\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 24)\n    #define FXAA_QUALITY__PS 7\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 3.0\n    #define FXAA_QUALITY__P6 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 25)\n    #define FXAA_QUALITY__PS 8\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 4.0\n    #define FXAA_QUALITY__P7 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 26)\n    #define FXAA_QUALITY__PS 9\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 4.0\n    #define FXAA_QUALITY__P8 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 27)\n    #define FXAA_QUALITY__PS 10\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 4.0\n    #define FXAA_QUALITY__P9 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 28)\n    #define FXAA_QUALITY__PS 11\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 4.0\n    #define FXAA_QUALITY__P10 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 29)\n    #define FXAA_QUALITY__PS 12\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.5\n    #define FXAA_QUALITY__P2 2.0\n    #define FXAA_QUALITY__P3 2.0\n    #define FXAA_QUALITY__P4 2.0\n    #define FXAA_QUALITY__P5 2.0\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 2.0\n    #define FXAA_QUALITY__P10 4.0\n    #define FXAA_QUALITY__P11 8.0\n#endif\n#if (FXAA_QUALITY__PRESET == 39)\n    #define FXAA_QUALITY__PS 12\n    #define FXAA_QUALITY__P0 1.0\n    #define FXAA_QUALITY__P1 1.0\n    #define FXAA_QUALITY__P2 1.0\n    #define FXAA_QUALITY__P3 1.0\n    #define FXAA_QUALITY__P4 1.0\n    #define FXAA_QUALITY__P5 1.5\n    #define FXAA_QUALITY__P6 2.0\n    #define FXAA_QUALITY__P7 2.0\n    #define FXAA_QUALITY__P8 2.0\n    #define FXAA_QUALITY__P9 2.0\n    #define FXAA_QUALITY__P10 4.0\n    #define FXAA_QUALITY__P11 8.0\n#endif\n#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) || (FXAA_WebGL == 1)\n    #define FxaaBool bool\n    #define FxaaDiscard discard\n    #define FxaaFloat float\n    #define FxaaFloat2 vec2\n    #define FxaaFloat3 vec3\n    #define FxaaFloat4 vec4\n    #define FxaaHalf float\n    #define FxaaHalf2 vec2\n    #define FxaaHalf3 vec3\n    #define FxaaHalf4 vec4\n    #define FxaaInt2 ivec2\n    #define FxaaSat(x) clamp(x, 0.0, 1.0)\n    #define FxaaTex sampler2D\n#else\n    #define FxaaBool bool\n    #define FxaaDiscard clip(-1)\n    #define FxaaFloat float\n    #define FxaaFloat2 float2\n    #define FxaaFloat3 float3\n    #define FxaaFloat4 float4\n    #define FxaaHalf half\n    #define FxaaHalf2 half2\n    #define FxaaHalf3 half3\n    #define FxaaHalf4 half4\n    #define FxaaSat(x) saturate(x)\n#endif\n#if (FXAA_WebGL == 1)\n    #define FxaaTexTop(t, p) texture2D(t, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) texture2D(t, p + (vec2(o) * r), 0.0)\n#endif\n#if (FXAA_GLSL_120 == 1)\n    #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)\n    #if (FXAA_FAST_PIXEL_OFFSET == 1)\n        #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)\n    #else\n        #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)\n    #endif\n    #if (FXAA_GATHER4_ALPHA == 1)\n        #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)\n        #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)\n        #define FxaaTexGreen4(t, p) textureGather(t, p, 1)\n        #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)\n    #endif\n#endif\n#if (FXAA_GLSL_130 == 1)\n    #define FxaaTexTop(t, p) textureLod(t, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)\n    #if (FXAA_GATHER4_ALPHA == 1)\n        #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)\n        #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)\n        #define FxaaTexGreen4(t, p) textureGather(t, p, 1)\n        #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)\n    #endif\n#endif\n#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)\n    #define FxaaInt2 float2\n    #define FxaaTex sampler2D\n    #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))\n    #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))\n#endif\n#if (FXAA_HLSL_4 == 1)\n    #define FxaaInt2 int2\n    struct FxaaTex { SamplerState smpl; Texture2D tex; };\n    #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)\n#endif\n#if (FXAA_HLSL_5 == 1)\n    #define FxaaInt2 int2\n    struct FxaaTex { SamplerState smpl; Texture2D tex; };\n    #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)\n    #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)\n    #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)\n    #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)\n    #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)\n    #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)\n#endif\n#if (FXAA_GREEN_AS_LUMA == 0)\n    FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }\n#else\n    FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }\n#endif    \n#if (FXAA_PC == 1)\nFxaaFloat4 FxaaPixelShader(\n    FxaaFloat2 pos\n    #if (FXAA_PS3 == 1)\n        ,FxaaFloat4 fxaaConsolePosPos\n    #endif\n    ,FxaaTex tex\n    #if (FXAA_360_OPT == 1)\n        ,FxaaTex fxaaConsole360TexExpBiasNegOne\n        ,FxaaTex fxaaConsole360TexExpBiasNegTwo\n    #endif\n    ,FxaaFloat2 fxaaQualityRcpFrame\n    #if (FXAA_PS3 == 1) || (FXAA_360 == 1) || (FXAA_360_OPT == 1) || (FXAA_PC_CONSOLE == 1)\n        ,FxaaFloat4 fxaaConsoleRcpFrameOpt\n        ,FxaaFloat4 fxaaConsoleRcpFrameOpt2\n        ,FxaaFloat4 fxaaConsole360RcpFrameOpt2\n    #endif\n    ,FxaaFloat fxaaQualitySubpix\n    ,FxaaFloat fxaaQualityEdgeThreshold\n    ,FxaaFloat fxaaQualityEdgeThresholdMin\n    #if (FXAA_PS3 == 1) || (FXAA_360 == 1) || (FXAA_360_OPT == 1) || (FXAA_PC_CONSOLE == 1)\n        ,FxaaFloat fxaaConsoleEdgeSharpness\n        ,FxaaFloat fxaaConsoleEdgeThreshold\n        ,FxaaFloat fxaaConsoleEdgeThresholdMin\n    #endif\n    #if (FXAA_360 == 1) || (FXAA_360_OPT == 1)\n        ,FxaaFloat4 fxaaConsole360ConstDir\n    #endif\n) {\n    FxaaFloat2 posM;\n    posM.x = pos.x;\n    posM.y = pos.y;\n    #if (FXAA_GATHER4_ALPHA == 1)\n        #if (FXAA_DISCARD == 0)\n            FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);\n            #if (FXAA_GREEN_AS_LUMA == 0)\n                #define lumaM rgbyM.w\n            #else\n                #define lumaM rgbyM.y\n            #endif\n        #endif\n        #if (FXAA_GREEN_AS_LUMA == 0)\n            FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);\n            FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));\n        #else\n            FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);\n            FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));\n        #endif\n        #if (FXAA_DISCARD == 1)\n            #define lumaM luma4A.w\n        #endif\n        #define lumaE luma4A.z\n        #define lumaS luma4A.x\n        #define lumaSE luma4A.y\n        #define lumaNW luma4B.w\n        #define lumaN luma4B.z\n        #define lumaW luma4B.x\n    #else\n        FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);\n        #if (FXAA_GREEN_AS_LUMA == 0)\n            #define lumaM rgbyM.w\n        #else\n            #define lumaM rgbyM.y\n        #endif\n        FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));\n    #endif\n    FxaaFloat maxSM = max(lumaS, lumaM);\n    FxaaFloat minSM = min(lumaS, lumaM);\n    FxaaFloat maxESM = max(lumaE, maxSM);\n    FxaaFloat minESM = min(lumaE, minSM);\n    FxaaFloat maxWN = max(lumaN, lumaW);\n    FxaaFloat minWN = min(lumaN, lumaW);\n    FxaaFloat rangeMax = max(maxWN, maxESM);\n    FxaaFloat rangeMin = min(minWN, minESM);\n    FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;\n    FxaaFloat range = rangeMax - rangeMin;\n    FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);\n    FxaaBool earlyExit = range < rangeMaxClamped;\n    if(earlyExit)\n        #if (FXAA_DISCARD == 1)\n            FxaaDiscard;\n        #else\n            return rgbyM;\n        #endif\n    #if (FXAA_GATHER4_ALPHA == 0)\n        FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));\n    #else\n        FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));\n        FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));\n    #endif\n    FxaaFloat lumaNS = lumaN + lumaS;\n    FxaaFloat lumaWE = lumaW + lumaE;\n    FxaaFloat subpixRcpRange = 1.0/range;\n    FxaaFloat subpixNSWE = lumaNS + lumaWE;\n    FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;\n    FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;\n    FxaaFloat lumaNESE = lumaNE + lumaSE;\n    FxaaFloat lumaNWNE = lumaNW + lumaNE;\n    FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;\n    FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;\n    FxaaFloat lumaNWSW = lumaNW + lumaSW;\n    FxaaFloat lumaSWSE = lumaSW + lumaSE;\n    FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);\n    FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);\n    FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;\n    FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;\n    FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;\n    FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;\n    FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;\n    FxaaFloat lengthSign = fxaaQualityRcpFrame.x;\n    FxaaBool horzSpan = edgeHorz >= edgeVert;\n    FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;\n    if(!horzSpan) lumaN = lumaW;\n    if(!horzSpan) lumaS = lumaE;\n    if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;\n    FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;\n    FxaaFloat gradientN = lumaN - lumaM;\n    FxaaFloat gradientS = lumaS - lumaM;\n    FxaaFloat lumaNN = lumaN + lumaM;\n    FxaaFloat lumaSS = lumaS + lumaM;\n    FxaaBool pairN = abs(gradientN) >= abs(gradientS);\n    FxaaFloat gradient = max(abs(gradientN), abs(gradientS));\n    if(pairN) lengthSign = -lengthSign;\n    FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);\n    FxaaFloat2 posB;\n    posB.x = posM.x;\n    posB.y = posM.y;\n    FxaaFloat2 offNP;\n    offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n    offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n    if(!horzSpan) posB.x += lengthSign * 0.5;\n    if( horzSpan) posB.y += lengthSign * 0.5;\n    FxaaFloat2 posN;\n    posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;\n    posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;\n    FxaaFloat2 posP;\n    posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;\n    posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;\n    FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;\n    FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));\n    FxaaFloat subpixE = subpixC * subpixC;\n    FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));\n    if(!pairN) lumaNN = lumaSS;\n    FxaaFloat gradientScaled = gradient * 1.0/4.0;\n    FxaaFloat lumaMM = lumaM - lumaNN * 0.5;\n    FxaaFloat subpixF = subpixD * subpixE;\n    FxaaBool lumaMLTZero = lumaMM < 0.0;\n    lumaEndN -= lumaNN * 0.5;\n    lumaEndP -= lumaNN * 0.5;\n    FxaaBool doneN = abs(lumaEndN) >= gradientScaled;\n    FxaaBool doneP = abs(lumaEndP) >= gradientScaled;\n    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;\n    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;\n    FxaaBool doneNP = (!doneN) || (!doneP);\n    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;\n    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;\n    if(doneNP) {\n        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n        doneN = abs(lumaEndN) >= gradientScaled;\n        doneP = abs(lumaEndP) >= gradientScaled;\n        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;\n        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;\n        doneNP = (!doneN) || (!doneP);\n        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;\n        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;\n        #if (FXAA_QUALITY__PS > 3)\n        if(doneNP) {\n            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n            doneN = abs(lumaEndN) >= gradientScaled;\n            doneP = abs(lumaEndP) >= gradientScaled;\n            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;\n            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;\n            doneNP = (!doneN) || (!doneP);\n            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;\n            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;\n            #if (FXAA_QUALITY__PS > 4)\n            if(doneNP) {\n                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                doneN = abs(lumaEndN) >= gradientScaled;\n                doneP = abs(lumaEndP) >= gradientScaled;\n                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;\n                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;\n                doneNP = (!doneN) || (!doneP);\n                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;\n                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;\n                #if (FXAA_QUALITY__PS > 5)\n                if(doneNP) {\n                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                    doneN = abs(lumaEndN) >= gradientScaled;\n                    doneP = abs(lumaEndP) >= gradientScaled;\n                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;\n                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;\n                    doneNP = (!doneN) || (!doneP);\n                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;\n                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;\n                    #if (FXAA_QUALITY__PS > 6)\n                    if(doneNP) {\n                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                        doneN = abs(lumaEndN) >= gradientScaled;\n                        doneP = abs(lumaEndP) >= gradientScaled;\n                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;\n                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;\n                        doneNP = (!doneN) || (!doneP);\n                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;\n                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;\n                        #if (FXAA_QUALITY__PS > 7)\n                        if(doneNP) {\n                            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                            doneN = abs(lumaEndN) >= gradientScaled;\n                            doneP = abs(lumaEndP) >= gradientScaled;\n                            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;\n                            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;\n                            doneNP = (!doneN) || (!doneP);\n                            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;\n                            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;\n    #if (FXAA_QUALITY__PS > 8)\n    if(doneNP) {\n        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n        doneN = abs(lumaEndN) >= gradientScaled;\n        doneP = abs(lumaEndP) >= gradientScaled;\n        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;\n        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;\n        doneNP = (!doneN) || (!doneP);\n        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;\n        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;\n        #if (FXAA_QUALITY__PS > 9)\n        if(doneNP) {\n            if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n            if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n            if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n            if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n            doneN = abs(lumaEndN) >= gradientScaled;\n            doneP = abs(lumaEndP) >= gradientScaled;\n            if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;\n            if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;\n            doneNP = (!doneN) || (!doneP);\n            if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;\n            if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;\n            #if (FXAA_QUALITY__PS > 10)\n            if(doneNP) {\n                if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                doneN = abs(lumaEndN) >= gradientScaled;\n                doneP = abs(lumaEndP) >= gradientScaled;\n                if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;\n                if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;\n                doneNP = (!doneN) || (!doneP);\n                if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;\n                if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;\n                #if (FXAA_QUALITY__PS > 11)\n                if(doneNP) {\n                    if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                    if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                    if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                    if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                    doneN = abs(lumaEndN) >= gradientScaled;\n                    doneP = abs(lumaEndP) >= gradientScaled;\n                    if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;\n                    if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;\n                    doneNP = (!doneN) || (!doneP);\n                    if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;\n                    if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;\n                    #if (FXAA_QUALITY__PS > 12)\n                    if(doneNP) {\n                        if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));\n                        if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));\n                        if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n                        if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n                        doneN = abs(lumaEndN) >= gradientScaled;\n                        doneP = abs(lumaEndP) >= gradientScaled;\n                        if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;\n                        if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;\n                        doneNP = (!doneN) || (!doneP);\n                        if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;\n                        if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;\n                    }\n                    #endif\n                }\n                #endif\n            }\n            #endif\n        }\n        #endif\n    }\n    #endif\n                        }\n                        #endif\n                    }\n                    #endif\n                }\n                #endif\n            }\n            #endif\n        }\n        #endif\n    }\n    FxaaFloat dstN = posM.x - posN.x;\n    FxaaFloat dstP = posP.x - posM.x;\n    if(!horzSpan) dstN = posM.y - posN.y;\n    if(!horzSpan) dstP = posP.y - posM.y;\n    FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;\n    FxaaFloat spanLength = (dstP + dstN);\n    FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;\n    FxaaFloat spanLengthRcp = 1.0/spanLength;\n    FxaaBool directionN = dstN < dstP;\n    FxaaFloat dst = min(dstN, dstP);\n    FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;\n    FxaaFloat subpixG = subpixF * subpixF;\n    FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;\n    FxaaFloat subpixH = subpixG * fxaaQualitySubpix;\n    FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;\n    FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);\n    if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;\n    if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;\n    #if (FXAA_DISCARD == 1)\n        return FxaaTexTop(tex, posM);\n    #else\n        return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);\n    #endif\n}\n#endif\n#if (FXAA_PC_CONSOLE == 1)\nFxaaFloat4 FxaaPixelShader(\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n    FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));\n    FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));\n    FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));\n    FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));\n    FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        FxaaFloat lumaM = rgbyM.w;\n    #else\n        FxaaFloat lumaM = rgbyM.y;\n    #endif\n    FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);\n    lumaNe += 1.0/384.0;\n    FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);\n    FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);\n    FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);\n    FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);\n    FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);\n    FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;\n    FxaaFloat lumaMinM = min(lumaMin, lumaM);\n    FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);\n    FxaaFloat lumaMaxM = max(lumaMax, lumaM);\n    FxaaFloat dirSwMinusNe = lumaSw - lumaNe;\n    FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;\n    FxaaFloat dirSeMinusNw = lumaSe - lumaNw;\n    if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;\n    FxaaFloat2 dir;\n    dir.x = dirSwMinusNe + dirSeMinusNw;\n    dir.y = dirSwMinusNe - dirSeMinusNw;\n    FxaaFloat2 dir1 = normalize(dir.xy);\n    FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);\n    FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);\n    FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;\n    FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);\n    FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);\n    FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);\n    FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;\n    FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);\n    #else\n        FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);\n    #endif\n    if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;\n    return rgbyB; }\n#endif\n#if (FXAA_360 == 1)\n[reduceTempRegUsage(4)]\nfloat4 FxaaPixelShader(\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n    float4 lumaNwNeSwSe;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        asm { \n            tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX =  0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY =  0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX =  0.5, OffsetY =  0.5, UseComputedLOD=false\n        };\n    #else\n        asm { \n            tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX =  0.5, OffsetY = -0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY =  0.5, UseComputedLOD=false\n            tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX =  0.5, OffsetY =  0.5, UseComputedLOD=false\n        };\n    #endif\n    lumaNwNeSwSe.y += 1.0/384.0;\n    float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);\n    float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);\n    float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);\n    float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);\n    float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        float lumaMinM = min(lumaMin, rgbyM.w);\n        float lumaMaxM = max(lumaMax, rgbyM.w);\n    #else\n        float lumaMinM = min(lumaMin, rgbyM.y);\n        float lumaMaxM = max(lumaMax, rgbyM.y);\n    #endif        \n    if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;\n    float2 dir;\n    dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);\n    dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);\n    dir = normalize(dir);\n    float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;\n    float4 dir2;\n    float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;\n    dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);\n    dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;\n    float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));\n    float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));\n    float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));\n    float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));\n    float4 rgbyA = rgbyN1 + rgbyP1;\n    float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;\n    float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB; \n    rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA; \n    return rgbyR; }\n#endif\n#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)\n#pragma regcount 7\n#pragma disablepc all\n#pragma option O3\n#pragma option OutColorPrec=fp16\n#pragma texformat default RGBA8\nhalf4 FxaaPixelShader(\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n    half4 dir;\n    half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        lumaNe.w += half(1.0/512.0);\n        dir.x = -lumaNe.w;\n        dir.z = -lumaNe.w;\n    #else\n        lumaNe.y += half(1.0/512.0);\n        dir.x = -lumaNe.y;\n        dir.z = -lumaNe.y;\n    #endif\n    half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x += lumaSw.w;\n        dir.z += lumaSw.w;\n    #else\n        dir.x += lumaSw.y;\n        dir.z += lumaSw.y;\n    #endif        \n    half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x -= lumaNw.w;\n        dir.z += lumaNw.w;\n    #else\n        dir.x -= lumaNw.y;\n        dir.z += lumaNw.y;\n    #endif\n    half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x += lumaSe.w;\n        dir.z -= lumaSe.w;\n    #else\n        dir.x += lumaSe.y;\n        dir.z -= lumaSe.y;\n    #endif\n    half4 dir1_pos;\n    dir1_pos.xy = normalize(dir.xyz).xz;\n    half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);\n    half4 dir2_pos;\n    dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));\n    dir1_pos.zw = pos.xy;\n    dir2_pos.zw = pos.xy;\n    half4 temp1N;\n    temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));\n    half4 rgby1;\n    rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));\n    rgby1 = (temp1N + rgby1) * 0.5;\n    half4 temp2N;\n    temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));\n    half4 rgby2;\n    rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));\n    rgby2 = (temp2N + rgby2) * 0.5;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));\n        half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));\n    #else\n        half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));\n        half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));\n    #endif        \n    rgby2 = (rgby2 + rgby1) * 0.5;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        bool twoTapLt = rgby2.w < lumaMin;\n        bool twoTapGt = rgby2.w > lumaMax;\n    #else\n        bool twoTapLt = rgby2.y < lumaMin;\n        bool twoTapGt = rgby2.y > lumaMax;\n    #endif\n    if(twoTapLt || twoTapGt) rgby2 = rgby1;\n    return rgby2; }\n#endif\n#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)\n#pragma regcount 7\n#pragma disablepc all\n#pragma option O2\n#pragma option OutColorPrec=fp16\n#pragma texformat default RGBA8\nhalf4 FxaaPixelShader(\n    FxaaFloat2 pos,\n    FxaaFloat4 fxaaConsolePosPos,\n    FxaaTex tex,\n    FxaaTex fxaaConsole360TexExpBiasNegOne,\n    FxaaTex fxaaConsole360TexExpBiasNegTwo,\n    FxaaFloat2 fxaaQualityRcpFrame,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt,\n    FxaaFloat4 fxaaConsoleRcpFrameOpt2,\n    FxaaFloat4 fxaaConsole360RcpFrameOpt2,\n    FxaaFloat fxaaQualitySubpix,\n    FxaaFloat fxaaQualityEdgeThreshold,\n    FxaaFloat fxaaQualityEdgeThresholdMin,\n    FxaaFloat fxaaConsoleEdgeSharpness,\n    FxaaFloat fxaaConsoleEdgeThreshold,\n    FxaaFloat fxaaConsoleEdgeThresholdMin,\n    FxaaFloat4 fxaaConsole360ConstDir\n) {\n    half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaNe = rgbyNe.w + half(1.0/512.0);\n    #else\n        half lumaNe = rgbyNe.y + half(1.0/512.0);\n    #endif\n    half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaSwNegNe = lumaSw.w - lumaNe;\n    #else\n        half lumaSwNegNe = lumaSw.y - lumaNe;\n    #endif\n    half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);\n        half lumaMinNwSw = min(lumaNw.w, lumaSw.w);\n    #else\n        half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);\n        half lumaMinNwSw = min(lumaNw.y, lumaSw.y);\n    #endif\n    half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half dirZ =  lumaNw.w + lumaSwNegNe;\n        half dirX = -lumaNw.w + lumaSwNegNe;\n    #else\n        half dirZ =  lumaNw.y + lumaSwNegNe;\n        half dirX = -lumaNw.y + lumaSwNegNe;\n    #endif\n    half3 dir;\n    dir.y = 0.0;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        dir.x =  lumaSe.w + dirX;\n        dir.z = -lumaSe.w + dirZ;\n        half lumaMinNeSe = min(lumaNe, lumaSe.w);\n    #else\n        dir.x =  lumaSe.y + dirX;\n        dir.z = -lumaSe.y + dirZ;\n        half lumaMinNeSe = min(lumaNe, lumaSe.y);\n    #endif\n    half4 dir1_pos;\n    dir1_pos.xy = normalize(dir).xz;\n    half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);\n    half4 dir2_pos;\n    dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));\n    dir1_pos.zw = pos.xy;\n    dir2_pos.zw = pos.xy;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxNeSe = max(lumaNe, lumaSe.w);\n    #else\n        half lumaMaxNeSe = max(lumaNe, lumaSe.y);\n    #endif\n    half4 temp1N;\n    temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));\n    half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);\n    half lumaMin = min(lumaMinNwSw, lumaMinNeSe);\n    half4 rgby1;\n    rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;\n    rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));\n    rgby1 = (temp1N + rgby1) * 0.5;\n    half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        half lumaMaxM = max(lumaMax, rgbyM.w);\n        half lumaMinM = min(lumaMin, rgbyM.w);\n    #else\n        half lumaMaxM = max(lumaMax, rgbyM.y);\n        half lumaMinM = min(lumaMin, rgbyM.y);\n    #endif\n    half4 temp2N;\n    temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));\n    half4 rgby2;\n    rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;\n    half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD;\n    rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));\n    rgby2 = (temp2N + rgby2) * 0.5;\n    rgby2 = (rgby2 + rgby1) * 0.5;\n    #if (FXAA_GREEN_AS_LUMA == 0)\n        bool twoTapLt = rgby2.w < lumaMin;\n        bool twoTapGt = rgby2.w > lumaMax;\n    #else\n        bool twoTapLt = rgby2.y < lumaMin;\n        bool twoTapGt = rgby2.y > lumaMax;\n    #endif\n    bool earlyExit = lumaRangeM < lumaMax;\n    bool twoTap = twoTapLt || twoTapGt;\n    if(twoTap) rgby2 = rgby1;\n    if(earlyExit) rgby2 = rgbyM;\n    return rgby2; }\n#endif\n"
  },
  {
    "path": "src/antialias/module.coffee",
    "content": "Rendernode = require '/rendernode'\nQuad = require '/webgl/quad'\n\nreturn class AntiAlias\n    constructor: (@gl, gui, @source) ->\n        gui.remember @\n        @node = new Rendernode @gl,\n            #program: get 'fxaa.shader'\n            program: get 'fxaa3_11.shader'\n            drawable: quad\n            \n        @subpixel_aa = 0.75\n        @contrast_treshold = 0.166\n        @edge_treshold = 0.0\n        folder = gui.addFolder('Antialias')\n        folder.add(@, 'subpixel_aa', 0.0, 1.0).name('Subpixel aa')\n        folder.add(@, 'contrast_treshold', 0.063, 0.333).name('Contrast Treshold')\n        folder.add(@, 'edge_treshold', 0.0, 0.0833).name('Edge Treshold')\n\n    apply: ->\n        @node.start()\n            .f('subpixel_aa', @subpixel_aa)\n            .f('contrast_treshold', @contrast_treshold)\n            .f('edge_treshold', @edge_treshold)\n            .clear()\n            .sampler('source', @source)\n            .draw()\n            .end()\n\n    resize: (width, height) ->\n        @node.resize width, height\n"
  },
  {
    "path": "src/antialias/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar AntiAlias, Quad, Rendernode;\n\nRendernode = require('/rendernode');\n\nQuad = require('/webgl/quad');\n\nreturn AntiAlias = (function() {\n\n  function AntiAlias(gl, gui, source) {\n    var folder;\n    this.gl = gl;\n    this.source = source;\n    gui.remember(this);\n    this.node = new Rendernode(this.gl, {\n      program: get('fxaa3_11.shader'),\n      drawable: quad\n    });\n    this.subpixel_aa = 0.75;\n    this.contrast_treshold = 0.166;\n    this.edge_treshold = 0.0;\n    folder = gui.addFolder('Antialias');\n    folder.add(this, 'subpixel_aa', 0.0, 1.0).name('Subpixel aa');\n    folder.add(this, 'contrast_treshold', 0.063, 0.333).name('Contrast Treshold');\n    folder.add(this, 'edge_treshold', 0.0, 0.0833).name('Edge Treshold');\n  }\n\n  AntiAlias.prototype.apply = function() {\n    return this.node.start().f('subpixel_aa', this.subpixel_aa).f('contrast_treshold', this.contrast_treshold).f('edge_treshold', this.edge_treshold).clear().sampler('source', this.source).draw().end();\n  };\n\n  AntiAlias.prototype.resize = function(width, height) {\n    return this.node.resize(width, height);\n  };\n\n  return AntiAlias;\n\n})();\n"
  },
  {
    "path": "src/application.coffee",
    "content": "schedule = require 'schedule'\nloading = require 'loading'\ncamera = require 'camera'\n\nQuad = require '/webgl/quad'\nCube = require '/webgl/cube'\n\nAntialias = require 'antialias'\n{LowresModel, Model} = require 'model'\nIllumination = require 'illumination'\nRendernode = require '/rendernode'\nWindows = require '/windows'\n{DeferredShadowMap} = require '/depth'\nSun = require 'sun'\nDeferredModel = require 'deferred_model'\nSSAO = require 'ssao'\n\nclass CompositingControl\n    constructor: (gui) ->\n        gui.remember @\n        @draw_probes = false\n        @gi = 1\n        @di = 1\n        @ao = 0.8\n        \n        folder = gui.addFolder('Compositing')\n        folder.add(@, 'draw_probes').name('Draw Probes')\n        folder.add(@, 'gi', 0.0, 2.0).name('Glob. Illum.')\n        folder.add(@, 'di', 0.0, 2.0).name('Direct. Illum.')\n        folder.add(@, 'ao', 0.0, 1.0).name('SSAO')\n\nclass Lighting extends require('events')\n    constructor: (gui) ->\n        gui.remember @\n        super()\n        @sunRadiance = 1.0\n        @skyRadiance = 1.0\n        @giGain = 1.0\n        @bounces = 3\n        @sunColor = [255, 255, 255]\n        @skyColor = [0x07, 0xcb, 0xf5]\n\n        @sun_radiance = [0,0,0]\n        @sky_radiance = [0,0,0]\n\n        folder = gui.addFolder('Lighting')\n        folder.addColor(@, 'sunColor').name('Sun Color').onChange @computeRadiance\n        folder.add(@, 'sunRadiance', 0.0, 20.0).name('Sun Radiance').onChange @computeRadiance\n        folder.addColor(@, 'skyColor').name('Sky Color').onChange @computeRadiance\n        folder.add(@, 'skyRadiance', 0.0, 20.0).name('Sky Radiance').onChange @computeRadiance\n        folder.add(@, 'giGain', 0.0, 20.0).name('GI-gain').onChange @update\n        folder.add(@, 'bounces', 1.0, 10.0).step(1).name('Bounces').onChange @bouncesChanged\n\n        @computeRadiance()\n\n        @lastbounces = @bounces\n\n    computeRadiance: =>\n        @sun_radiance[0] = @sunRadiance * (@sunColor[0]/255.0)\n        @sun_radiance[1] = @sunRadiance * (@sunColor[1]/255.0)\n        @sun_radiance[2] = @sunRadiance * (@sunColor[2]/255.0)\n        @sky_radiance[0] = @skyRadiance * (@skyColor[0]/255.0)\n        @sky_radiance[1] = @skyRadiance * (@skyColor[1]/255.0)\n        @sky_radiance[2] = @skyRadiance * (@skyColor[2]/255.0)\n        @update()\n\n    bouncesChanged: =>\n        if @bounces != @lastBounces\n            @lastBounces = @bounces\n            @update()\n\n    update: => @trigger('change')\n\nclass PictureSettings\n    constructor: (gui) ->\n        gui.remember @\n        @inputGamma = 1.8\n        @outputGamma = 1.8\n        @brightness = 1.0\n        @saturation = 1.0\n\n        folder = gui.addFolder('Picture')\n        folder.add(@, 'inputGamma', 0.25, 3.0).name('Input Gamma')\n        folder.add(@, 'outputGamma', 0.25, 3.0).name('Output Gamma')\n        folder.add(@, 'brightness', 0.0, 10.0).name('Exposure')\n        folder.add(@, 'saturation', 0.0, 4.0).name('Saturation')\n\nclass SHConstants\n    constructor: (@app, gui) ->\n        gui.remember @\n        @c1 = 0.43\n        @c2 = 0.66\n        @band3 = 1.0\n        @c3 = 0.9\n        @c4 = 0.34\n        @c5 = 0.43\n        \n        @data = new Float32Array(5)\n\n        folder = gui.addFolder('Harmonics')\n        folder.add(@, 'c1', 0.0, 4.0).name('L0').onChange @change\n        folder.add(@, 'c2', 0.0, 4.0).name('L1').onChange @change\n        folder.add(@, 'band3', 0.0, 4.0).name('L2').onChange @change\n        folder.add(@, 'c3', 0.0, 4.0).name('L2m2/L2m1/L21').onChange @change\n        folder.add(@, 'c4', 0.0, 4.0).name('L20').onChange @change\n        folder.add(@, 'c5', 0.0, 4.0).name('L22').onChange @change\n        \n        @updateData()\n\n    updateData: ->\n        @data[0] = @c1\n        @data[1] = @c2\n        @data[2] = @band3 * @c3\n        @data[3] = @band3 * @c4\n        @data[4] = @band3 * @c5\n\n    change: =>\n        @updateData()\n        @app.lightChange()\n\n\nmakeStat = (mode, offset) ->\n    stats = new Stats()\n    stats.setMode(mode)\n    node = $(stats.domElement)\n    node.css(\n            position: 'absolute'\n            left: offset\n            top: 0\n    ).appendTo('body').hide()\n\n    stats.hide = ->\n        node.clearQueue().fadeOut()\n    stats.show = ->\n        node.clearQueue().fadeIn()\n\n    return stats\n\nexports.Application = class\n    constructor: (@canvas) ->\n        $('<div id=\"controls\"></div>')\n            .css('margin', 10)\n            .appendTo('#ui')\n        Rendernode.stateDefaults(gl)\n        \n        gui = @gui = new dat.GUI\n            load: get 'presets/new.json'\n\n        gui.remember @\n        @gui_width = gui.width = 370\n        @gui.closed = false\n        @fps = makeStat(0, 0)\n        @rtime = makeStat(1, 80)\n        @gui_closed = gui.closed\n\n        @resolution = 0.5\n        @resolution_label = '1:2 default'\n        resmap =\n            '2:1 very slow!': 2\n            '1:1 slow': 1\n            '1:2 default': 0.5\n            '1:4 ugly': 0.25\n            '1:8 worse': 0.125\n\n        folder = gui.addFolder('Performance')\n        $('<li>WASD=move, space=overview, cursor keys=navigate</li>').appendTo(folder.__ul)\n        folder.add(@, 'resolution_label', ['2:1 very slow!', '1:1 slow', '1:2 default', '1:4 ugly', '1:8 worse']).name('Resolution').onChange =>\n            @resolution = resmap[@resolution_label]\n            @resizeBuffers()\n        @resolution = resmap[@resolution_label]\n\n        @show_fps = false\n        folder.add(@, 'show_fps').name('FPS').onChange =>\n            if @show_fps\n                @fps.show()\n                @rtime.show()\n            else\n                @fps.hide()\n                @rtime.hide()\n        if @show_fps\n            @fps.show()\n            @rtime.show()\n        else\n            @fps.hide()\n            @rtime.hide()\n        \n\n        @picture = new PictureSettings(gui)\n        @sun = new Sun(gui).on('change', @sunChanged)\n        @compositing_control = new CompositingControl(gui)\n        @lighting = new Lighting(gui).on('change', @lightChange)\n        @shconst = new SHConstants @, gui\n\n        loading.hide()\n        @near = 0.1\n        @far = 42\n\n        @camera = new camera.FlyCam(gui: gui, near: @near, far: @far, x: -10, y:7, z:-1.5, o:100, p:20)\n        @sponza = new Model gl\n        @lowres = new LowresModel gl\n\n        floatExt = gl.getFloatExtension require: ['renderable', 'filterable']\n        #highQualityExt = gl.getFloatExtension require: ['renderable', 'single']\n\n        @view_normaldepth = new Rendernode gl,\n            program: get 'normaldepth.shader'\n            drawable: @sponza\n            depthBuffer: true\n            depthTest: true\n            depthWrite: true\n            cullFace: 'BACK' #disabled because of mesh gaps\n            #type: gl.FLOAT #float is required to avoid banding issues (tried packing, doesn't come out well)\n            type: floatExt.type\n            #type: highQualityExt.type\n            filter: 'nearest'\n            hdrClear: true\n\n        @ssao = new SSAO gl, @view_normaldepth\n        \n        @direct_light = new DeferredShadowMap gl,\n            drawable: @sponza\n            depthWidth: 512\n            depthHeight: 512\n            eyeNormaldepth: @view_normaldepth\n            light: @sun\n            camera: @camera\n            blurred: true\n\n        @illumination = new Illumination gl, @sun, @lighting, @lowres, @sponza, @view_normaldepth, @sun.orientation, @sun.elevation, @shconst\n       \n        @albedo = new Rendernode gl,\n            program: get 'albedo.shader'\n            drawable: @sponza\n            depthBuffer: true\n            depthTest: true\n            depthWrite: true\n            #cullFace: 'BACK' #disabled because of mesh gaps\n            #type: gl.FLOAT #not really required, adds little, the source is bytes anyway\n\n        @global_illumination = new Rendernode gl,\n            program: get 'global_illumination.shader'\n            drawable: new DeferredModel gl, @illumination.probes\n            cullFace: 'FRONT'\n            blend: 'additive'\n            #type: gl.FLOAT #float is required because of additive summation, does not yield a perf benefit\n            type: floatExt.type,\n            depthBuffer: @view_normaldepth.depth # early z gives some performance\n            depthWrite: false\n            depthTest: 'GEQUAL'\n        \n        @composit = new Rendernode gl,\n            program: get 'composit.shader'\n            drawable: quad\n\n        @antialias = new Antialias gl, gui, @composit\n        \n        @windows = new Windows gl, gui, [\n                {label: 'Scene depth from sun', affine: [1, 0], gamma: false, tex: @direct_light.depth.output},\n                {label: 'Scene normal/depth', affine: [0.5, 0.5], gamma: false, tex: @view_normaldepth},\n                #{label: 'Scene normal/depth', affine: [0.1, 0.0], gamma: false, tex: @view_normaldepth},\n                {label: 'Scene depth moments', gamma: false, tex: @ssao.blur.output},\n                {label: 'Direct Illumination Lightmap', tex: @illumination.direct_light.output},\n                {label: 'Global Illumination Lightmap', diva: true, tex: @illumination.bounce},\n                {label: 'Lightmap Dictionary', tex: @illumination.texmap},\n                {label: 'Albedo Probe Values', tex: @illumination.diffusemap},\n                {label: 'Light Probes', tex: @illumination.lightprobes},\n                {label: 'Spherical Harmonics Coefficients', tex: @illumination.coefficients},\n                {label: 'Albedo', tex: @albedo},\n                {label: 'SSAO', gamma: false, tex: @ssao.output},\n                {label: 'Direct Illumination', tex: @direct_light.output},\n                {label: 'Global Illumination', diva: true, tex: @global_illumination},\n                {label: 'Composited', gamma: false, tex: @composit},\n                {label: 'Antialiased', gamma: false, tex: @antialias.node},\n            ]\n       \n\n        @target_width = @canvas.width()\n        @current_width = @target_width\n\n        $(window).resize @resize\n        @resize()\n        schedule.run @update\n        @canvas.fadeIn(2000)\n        $('div.dg > ul').css('margin-top', 0)\n\n    sunChanged: =>\n        @direct_light.updateDepth()\n        @illumination.updateDirectLight()\n        @lightChange()\n\n    lightChange: =>\n        @illumination.update()\n\n    resizeBuffers: (width, height) ->\n        w = @width*@resolution\n        h = @height*@resolution\n\n        @view_normaldepth.resize w, h\n        @albedo.resize w, h\n        @global_illumination.resize w, h\n        @direct_light.resize w, h\n        @composit.resize w, h\n        @antialias.resize w, h\n        @illumination.debug.resize w, h\n        @ssao.resize w, h\n        \n    resize: =>\n        @width = @canvas.width()\n        @height = @canvas.height()\n        @camera.aspect @width, @height\n\n        @canvas[0].width = @width\n        @canvas[0].height = @height\n\n        @resizeBuffers @width, @height\n        @resizeWindows()\n\n    update: =>\n        @fps.end()\n        @fps.begin()\n        @rtime.begin()\n        @step()\n        @draw()\n        @rtime.end()\n    \n    resizeWindows: ->\n        @windows.node.viewport 0, 0, @current_width, @height\n\n    step: ->\n        gui_closed = @gui.closed\n        if gui_closed\n            @target_width = @width\n        else\n            gui_width = @gui.width\n            @target_width = @width - (gui_width+10)\n\n\n        dw = @target_width - @current_width\n        @current_width = @current_width+dw*0.1\n\n        dw = Math.abs(@target_width - @current_width)\n\n        if dw > 1\n            @resizeWindows()\n        else if dw <= 1 and dw > 0\n            @current_width = @target_width\n            @resizeWindows()\n\n        @camera.update()\n\n    draw: ->\n        #@illumination.update() #TODO\n        @view_normaldepth\n            .clear(0, 0, 0, 100)\n            .start()\n            .clearDepth()\n            .mat4('proj', @camera.proj)\n            .mat4('view', @camera.view)\n            .mat3('view_rot', @camera.rot)\n            .drawModel('bumpmap')\n            .end()\n\n        @ssao.update()\n        \n        @albedo.start()\n            .f('gamma', @picture.inputGamma)\n            .mat4('proj', @camera.proj)\n            .mat4('view', @camera.view)\n            .mat3('view_rot', @camera.rot)\n            .clearBoth(0, 0, 0, 0)\n            .drawModel('diffuse_texture')\n            .end()\n      \n        @global_illumination.start()\n            .f('gi_gain', @lighting.giGain)\n            .fv('shconst', @shconst.data)\n            .sampler('normaldepth', @view_normaldepth)\n            .mat4('proj', @camera.proj)\n            .mat4('view', @camera.view)\n            .mat4('inv_view', @camera.inv_view)\n            .sampler('coefficients', @illumination.coefficients)\n            .val2('coefficients_size', @illumination.coefficients.width, @illumination.coefficients.height)\n            .clear()\n            .draw()\n            .end()\n\n        @direct_light.updateShadow()\n\n        if @compositing_control.draw_probes\n            probe_factor = 1\n            @illumination.drawDebug(@camera, @view_normaldepth)\n        else\n            probe_factor = 0\n\n        @composit.start()\n            .clear()\n            .f('gamma', @picture.outputGamma)\n            .f('brightness', @picture.brightness)\n            .f('saturation', @picture.saturation)\n            .vec3('sun_radiance', @lighting.sun_radiance)\n            .vec3('sky_radiance', @lighting.sky_radiance)\n            .f('probe_factor', probe_factor)\n            .f('gi_factor', @compositing_control.gi)\n            .f('di_factor', @compositing_control.di)\n            .f('ao_factor', @compositing_control.ao)\n            .vec3('sky_color', @lighting.skyColor)\n            .sampler('debug', @illumination.debug)\n            .sampler('albedo', @albedo)\n            .sampler('global', @global_illumination)\n            .sampler('direct', @direct_light.output)\n            .sampler('ssao', @ssao.output)\n            .draw()\n            .end()\n       \n        @antialias.apply()\n\n        @windows.draw(@picture.outputGamma)\n"
  },
  {
    "path": "src/application.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Antialias, CompositingControl, Cube, DeferredModel, DeferredShadowMap, Illumination, Lighting, LowresModel, Model, PictureSettings, Quad, Rendernode, SHConstants, SSAO, Sun, Windows, camera, loading, makeStat, schedule, _ref,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nschedule = require('schedule');\n\nloading = require('loading');\n\ncamera = require('camera');\n\nQuad = require('/webgl/quad');\n\nCube = require('/webgl/cube');\n\nAntialias = require('antialias');\n\n_ref = require('model'), LowresModel = _ref.LowresModel, Model = _ref.Model;\n\nIllumination = require('illumination');\n\nRendernode = require('/rendernode');\n\nWindows = require('/windows');\n\nDeferredShadowMap = require('/depth').DeferredShadowMap;\n\nSun = require('sun');\n\nDeferredModel = require('deferred_model');\n\nSSAO = require('ssao');\n\nCompositingControl = (function() {\n\n  function CompositingControl(gui) {\n    var folder;\n    gui.remember(this);\n    this.draw_probes = false;\n    this.gi = 1;\n    this.di = 1;\n    this.ao = 0.8;\n    folder = gui.addFolder('Compositing');\n    folder.add(this, 'draw_probes').name('Draw Probes');\n    folder.add(this, 'gi', 0.0, 2.0).name('Glob. Illum.');\n    folder.add(this, 'di', 0.0, 2.0).name('Direct. Illum.');\n    folder.add(this, 'ao', 0.0, 1.0).name('SSAO');\n  }\n\n  return CompositingControl;\n\n})();\n\nLighting = (function(_super) {\n\n  __extends(Lighting, _super);\n\n  function Lighting(gui) {\n    this.update = __bind(this.update, this);\n\n    this.bouncesChanged = __bind(this.bouncesChanged, this);\n\n    this.computeRadiance = __bind(this.computeRadiance, this);\n\n    var folder;\n    gui.remember(this);\n    Lighting.__super__.constructor.call(this);\n    this.sunRadiance = 1.0;\n    this.skyRadiance = 1.0;\n    this.giGain = 1.0;\n    this.bounces = 3;\n    this.sunColor = [255, 255, 255];\n    this.skyColor = [0x07, 0xcb, 0xf5];\n    this.sun_radiance = [0, 0, 0];\n    this.sky_radiance = [0, 0, 0];\n    folder = gui.addFolder('Lighting');\n    folder.addColor(this, 'sunColor').name('Sun Color').onChange(this.computeRadiance);\n    folder.add(this, 'sunRadiance', 0.0, 20.0).name('Sun Radiance').onChange(this.computeRadiance);\n    folder.addColor(this, 'skyColor').name('Sky Color').onChange(this.computeRadiance);\n    folder.add(this, 'skyRadiance', 0.0, 20.0).name('Sky Radiance').onChange(this.computeRadiance);\n    folder.add(this, 'giGain', 0.0, 20.0).name('GI-gain').onChange(this.update);\n    folder.add(this, 'bounces', 1.0, 10.0).step(1).name('Bounces').onChange(this.bouncesChanged);\n    this.computeRadiance();\n    this.lastbounces = this.bounces;\n  }\n\n  Lighting.prototype.computeRadiance = function() {\n    this.sun_radiance[0] = this.sunRadiance * (this.sunColor[0] / 255.0);\n    this.sun_radiance[1] = this.sunRadiance * (this.sunColor[1] / 255.0);\n    this.sun_radiance[2] = this.sunRadiance * (this.sunColor[2] / 255.0);\n    this.sky_radiance[0] = this.skyRadiance * (this.skyColor[0] / 255.0);\n    this.sky_radiance[1] = this.skyRadiance * (this.skyColor[1] / 255.0);\n    this.sky_radiance[2] = this.skyRadiance * (this.skyColor[2] / 255.0);\n    return this.update();\n  };\n\n  Lighting.prototype.bouncesChanged = function() {\n    if (this.bounces !== this.lastBounces) {\n      this.lastBounces = this.bounces;\n      return this.update();\n    }\n  };\n\n  Lighting.prototype.update = function() {\n    return this.trigger('change');\n  };\n\n  return Lighting;\n\n})(require('events'));\n\nPictureSettings = (function() {\n\n  function PictureSettings(gui) {\n    var folder;\n    gui.remember(this);\n    this.inputGamma = 1.8;\n    this.outputGamma = 1.8;\n    this.brightness = 1.0;\n    this.saturation = 1.0;\n    folder = gui.addFolder('Picture');\n    folder.add(this, 'inputGamma', 0.25, 3.0).name('Input Gamma');\n    folder.add(this, 'outputGamma', 0.25, 3.0).name('Output Gamma');\n    folder.add(this, 'brightness', 0.0, 10.0).name('Exposure');\n    folder.add(this, 'saturation', 0.0, 4.0).name('Saturation');\n  }\n\n  return PictureSettings;\n\n})();\n\nSHConstants = (function() {\n\n  function SHConstants(app, gui) {\n    var folder;\n    this.app = app;\n    this.change = __bind(this.change, this);\n\n    gui.remember(this);\n    this.c1 = 0.43;\n    this.c2 = 0.66;\n    this.band3 = 1.0;\n    this.c3 = 0.9;\n    this.c4 = 0.34;\n    this.c5 = 0.43;\n    this.data = new Float32Array(5);\n    folder = gui.addFolder('Harmonics');\n    folder.add(this, 'c1', 0.0, 4.0).name('L0').onChange(this.change);\n    folder.add(this, 'c2', 0.0, 4.0).name('L1').onChange(this.change);\n    folder.add(this, 'band3', 0.0, 4.0).name('L2').onChange(this.change);\n    folder.add(this, 'c3', 0.0, 4.0).name('L2m2/L2m1/L21').onChange(this.change);\n    folder.add(this, 'c4', 0.0, 4.0).name('L20').onChange(this.change);\n    folder.add(this, 'c5', 0.0, 4.0).name('L22').onChange(this.change);\n    this.updateData();\n  }\n\n  SHConstants.prototype.updateData = function() {\n    this.data[0] = this.c1;\n    this.data[1] = this.c2;\n    this.data[2] = this.band3 * this.c3;\n    this.data[3] = this.band3 * this.c4;\n    return this.data[4] = this.band3 * this.c5;\n  };\n\n  SHConstants.prototype.change = function() {\n    this.updateData();\n    return this.app.lightChange();\n  };\n\n  return SHConstants;\n\n})();\n\nmakeStat = function(mode, offset) {\n  var node, stats;\n  stats = new Stats();\n  stats.setMode(mode);\n  node = $(stats.domElement);\n  node.css({\n    position: 'absolute',\n    left: offset,\n    top: 0\n  }).appendTo('body').hide();\n  stats.hide = function() {\n    return node.clearQueue().fadeOut();\n  };\n  stats.show = function() {\n    return node.clearQueue().fadeIn();\n  };\n  return stats;\n};\n\nexports.Application = (function() {\n\n  function _Class(canvas) {\n    var floatExt, folder, gui, resmap,\n      _this = this;\n    this.canvas = canvas;\n    this.update = __bind(this.update, this);\n\n    this.resize = __bind(this.resize, this);\n\n    this.lightChange = __bind(this.lightChange, this);\n\n    this.sunChanged = __bind(this.sunChanged, this);\n\n    $('<div id=\"controls\"></div>').css('margin', 10).appendTo('#ui');\n    Rendernode.stateDefaults(gl);\n    gui = this.gui = new dat.GUI({\n      load: get('presets/new.json')\n    });\n    gui.remember(this);\n    this.gui_width = gui.width = 370;\n    this.gui.closed = false;\n    this.fps = makeStat(0, 0);\n    this.rtime = makeStat(1, 80);\n    this.gui_closed = gui.closed;\n    this.resolution = 0.5;\n    this.resolution_label = '1:2 default';\n    resmap = {\n      '2:1 very slow!': 2,\n      '1:1 slow': 1,\n      '1:2 default': 0.5,\n      '1:4 ugly': 0.25,\n      '1:8 worse': 0.125\n    };\n    folder = gui.addFolder('Performance');\n    $('<li>WASD=move, space=overview, cursor keys=navigate</li>').appendTo(folder.__ul);\n    folder.add(this, 'resolution_label', ['2:1 very slow!', '1:1 slow', '1:2 default', '1:4 ugly', '1:8 worse']).name('Resolution').onChange(function() {\n      _this.resolution = resmap[_this.resolution_label];\n      return _this.resizeBuffers();\n    });\n    this.resolution = resmap[this.resolution_label];\n    this.show_fps = false;\n    folder.add(this, 'show_fps').name('FPS').onChange(function() {\n      if (_this.show_fps) {\n        _this.fps.show();\n        return _this.rtime.show();\n      } else {\n        _this.fps.hide();\n        return _this.rtime.hide();\n      }\n    });\n    if (this.show_fps) {\n      this.fps.show();\n      this.rtime.show();\n    } else {\n      this.fps.hide();\n      this.rtime.hide();\n    }\n    this.picture = new PictureSettings(gui);\n    this.sun = new Sun(gui).on('change', this.sunChanged);\n    this.compositing_control = new CompositingControl(gui);\n    this.lighting = new Lighting(gui).on('change', this.lightChange);\n    this.shconst = new SHConstants(this, gui);\n    loading.hide();\n    this.near = 0.1;\n    this.far = 42;\n    this.camera = new camera.FlyCam({\n      gui: gui,\n      near: this.near,\n      far: this.far,\n      x: -10,\n      y: 7,\n      z: -1.5,\n      o: 100,\n      p: 20\n    });\n    this.sponza = new Model(gl);\n    this.lowres = new LowresModel(gl);\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.view_normaldepth = new Rendernode(gl, {\n      program: get('normaldepth.shader'),\n      drawable: this.sponza,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      cullFace: 'BACK',\n      type: floatExt.type,\n      filter: 'nearest',\n      hdrClear: true\n    });\n    this.ssao = new SSAO(gl, this.view_normaldepth);\n    this.direct_light = new DeferredShadowMap(gl, {\n      drawable: this.sponza,\n      depthWidth: 512,\n      depthHeight: 512,\n      eyeNormaldepth: this.view_normaldepth,\n      light: this.sun,\n      camera: this.camera,\n      blurred: true\n    });\n    this.illumination = new Illumination(gl, this.sun, this.lighting, this.lowres, this.sponza, this.view_normaldepth, this.sun.orientation, this.sun.elevation, this.shconst);\n    this.albedo = new Rendernode(gl, {\n      program: get('albedo.shader'),\n      drawable: this.sponza,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true\n    });\n    this.global_illumination = new Rendernode(gl, {\n      program: get('global_illumination.shader'),\n      drawable: new DeferredModel(gl, this.illumination.probes),\n      cullFace: 'FRONT',\n      blend: 'additive',\n      type: floatExt.type,\n      depthBuffer: this.view_normaldepth.depth,\n      depthWrite: false,\n      depthTest: 'GEQUAL'\n    });\n    this.composit = new Rendernode(gl, {\n      program: get('composit.shader'),\n      drawable: quad\n    });\n    this.antialias = new Antialias(gl, gui, this.composit);\n    this.windows = new Windows(gl, gui, [\n      {\n        label: 'Scene depth from sun',\n        affine: [1, 0],\n        gamma: false,\n        tex: this.direct_light.depth.output\n      }, {\n        label: 'Scene normal/depth',\n        affine: [0.5, 0.5],\n        gamma: false,\n        tex: this.view_normaldepth\n      }, {\n        label: 'Scene depth moments',\n        gamma: false,\n        tex: this.ssao.blur.output\n      }, {\n        label: 'Direct Illumination Lightmap',\n        tex: this.illumination.direct_light.output\n      }, {\n        label: 'Global Illumination Lightmap',\n        diva: true,\n        tex: this.illumination.bounce\n      }, {\n        label: 'Lightmap Dictionary',\n        tex: this.illumination.texmap\n      }, {\n        label: 'Albedo Probe Values',\n        tex: this.illumination.diffusemap\n      }, {\n        label: 'Light Probes',\n        tex: this.illumination.lightprobes\n      }, {\n        label: 'Spherical Harmonics Coefficients',\n        tex: this.illumination.coefficients\n      }, {\n        label: 'Albedo',\n        tex: this.albedo\n      }, {\n        label: 'SSAO',\n        gamma: false,\n        tex: this.ssao.output\n      }, {\n        label: 'Direct Illumination',\n        tex: this.direct_light.output\n      }, {\n        label: 'Global Illumination',\n        diva: true,\n        tex: this.global_illumination\n      }, {\n        label: 'Composited',\n        gamma: false,\n        tex: this.composit\n      }, {\n        label: 'Antialiased',\n        gamma: false,\n        tex: this.antialias.node\n      }\n    ]);\n    this.target_width = this.canvas.width();\n    this.current_width = this.target_width;\n    $(window).resize(this.resize);\n    this.resize();\n    schedule.run(this.update);\n    this.canvas.fadeIn(2000);\n    $('div.dg > ul').css('margin-top', 0);\n  }\n\n  _Class.prototype.sunChanged = function() {\n    this.direct_light.updateDepth();\n    this.illumination.updateDirectLight();\n    return this.lightChange();\n  };\n\n  _Class.prototype.lightChange = function() {\n    return this.illumination.update();\n  };\n\n  _Class.prototype.resizeBuffers = function(width, height) {\n    var h, w;\n    w = this.width * this.resolution;\n    h = this.height * this.resolution;\n    this.view_normaldepth.resize(w, h);\n    this.albedo.resize(w, h);\n    this.global_illumination.resize(w, h);\n    this.direct_light.resize(w, h);\n    this.composit.resize(w, h);\n    this.antialias.resize(w, h);\n    this.illumination.debug.resize(w, h);\n    return this.ssao.resize(w, h);\n  };\n\n  _Class.prototype.resize = function() {\n    this.width = this.canvas.width();\n    this.height = this.canvas.height();\n    this.camera.aspect(this.width, this.height);\n    this.canvas[0].width = this.width;\n    this.canvas[0].height = this.height;\n    this.resizeBuffers(this.width, this.height);\n    return this.resizeWindows();\n  };\n\n  _Class.prototype.update = function() {\n    this.fps.end();\n    this.fps.begin();\n    this.rtime.begin();\n    this.step();\n    this.draw();\n    return this.rtime.end();\n  };\n\n  _Class.prototype.resizeWindows = function() {\n    return this.windows.node.viewport(0, 0, this.current_width, this.height);\n  };\n\n  _Class.prototype.step = function() {\n    var dw, gui_closed, gui_width;\n    gui_closed = this.gui.closed;\n    if (gui_closed) {\n      this.target_width = this.width;\n    } else {\n      gui_width = this.gui.width;\n      this.target_width = this.width - (gui_width + 10);\n    }\n    dw = this.target_width - this.current_width;\n    this.current_width = this.current_width + dw * 0.1;\n    dw = Math.abs(this.target_width - this.current_width);\n    if (dw > 1) {\n      this.resizeWindows();\n    } else if (dw <= 1 && dw > 0) {\n      this.current_width = this.target_width;\n      this.resizeWindows();\n    }\n    return this.camera.update();\n  };\n\n  _Class.prototype.draw = function() {\n    var probe_factor;\n    this.view_normaldepth.clear(0, 0, 0, 100).start().clearDepth().mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat3('view_rot', this.camera.rot).drawModel('bumpmap').end();\n    this.ssao.update();\n    this.albedo.start().f('gamma', this.picture.inputGamma).mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat3('view_rot', this.camera.rot).clearBoth(0, 0, 0, 0).drawModel('diffuse_texture').end();\n    this.global_illumination.start().f('gi_gain', this.lighting.giGain).fv('shconst', this.shconst.data).sampler('normaldepth', this.view_normaldepth).mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat4('inv_view', this.camera.inv_view).sampler('coefficients', this.illumination.coefficients).val2('coefficients_size', this.illumination.coefficients.width, this.illumination.coefficients.height).clear().draw().end();\n    this.direct_light.updateShadow();\n    if (this.compositing_control.draw_probes) {\n      probe_factor = 1;\n      this.illumination.drawDebug(this.camera, this.view_normaldepth);\n    } else {\n      probe_factor = 0;\n    }\n    this.composit.start().clear().f('gamma', this.picture.outputGamma).f('brightness', this.picture.brightness).f('saturation', this.picture.saturation).vec3('sun_radiance', this.lighting.sun_radiance).vec3('sky_radiance', this.lighting.sky_radiance).f('probe_factor', probe_factor).f('gi_factor', this.compositing_control.gi).f('di_factor', this.compositing_control.di).f('ao_factor', this.compositing_control.ao).vec3('sky_color', this.lighting.skyColor).sampler('debug', this.illumination.debug).sampler('albedo', this.albedo).sampler('global', this.global_illumination).sampler('direct', this.direct_light.output).sampler('ssao', this.ssao.output).draw().end();\n    this.antialias.apply();\n    return this.windows.draw(this.picture.outputGamma);\n  };\n\n  return _Class;\n\n})();\n"
  },
  {
    "path": "src/blur/blur.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D source;\n    uniform vec2 viewport;\n        \n    void main(){\n        vec4 sum = vec4(0.0);\n        float divider = 0.0;\n        for(float x=-2.0; x<=2.0; x++){\n            for(float y=-2.0; y<=2.0; y++){\n                vec2 coord = vec2(x,y);\n                float l = length(coord)+1.0;\n                float factor = 1.0/l;\n                divider += factor;\n                sum += texture2D(source, (gl_FragCoord.xy+vec2(x,y))/viewport) * factor;\n            }\n        }\n        gl_FragColor = sum/divider;\n    }\n"
  },
  {
    "path": "src/blur/module.coffee",
    "content": "Rendernode = require '/rendernode'\n\nreturn class Blur\n    constructor: (gl, {width, height, type, filter}) ->\n        type ?= gl.UNSIGNED_BYTE\n        filter ?= 'linear'\n\n        @output = new Rendernode gl,\n            width: width\n            height: height\n            program: get 'blur.shader'\n            drawable: quad\n            filter: filter\n            type: type\n\n    update: (source) ->\n        @output\n            .start()\n            .sampler('source', source)\n            .draw()\n            .end()\n\n    resize: (width, height) ->\n        @output.resize(width, height)\n"
  },
  {
    "path": "src/blur/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Blur, Rendernode;\n\nRendernode = require('/rendernode');\n\nreturn Blur = (function() {\n\n  function Blur(gl, _arg) {\n    var filter, height, type, width;\n    width = _arg.width, height = _arg.height, type = _arg.type, filter = _arg.filter;\n    if (type == null) {\n      type = gl.UNSIGNED_BYTE;\n    }\n    if (filter == null) {\n      filter = 'linear';\n    }\n    this.output = new Rendernode(gl, {\n      width: width,\n      height: height,\n      program: get('blur.shader'),\n      drawable: quad,\n      filter: filter,\n      type: type\n    });\n  }\n\n  Blur.prototype.update = function(source) {\n    return this.output.start().sampler('source', source).draw().end();\n  };\n\n  Blur.prototype.resize = function(width, height) {\n    return this.output.resize(width, height);\n  };\n\n  return Blur;\n\n})();\n"
  },
  {
    "path": "src/composit.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D global, direct, albedo, debug, ssao;\n    uniform vec2 viewport;\n    uniform float gamma, brightness, saturation;\n    uniform float probe_factor, di_factor, gi_factor, ao_factor;\n    uniform vec3 sky_radiance, sun_radiance;\n\n    void main(){\n        float occlusion = mix(1.0, texture2D(ssao, gl_FragCoord.xy/viewport).r, ao_factor);\n\n        vec4 global_data = texture2D(global, gl_FragCoord.xy/viewport);\n        vec3 global_irradiance = max(global_data.rgb/global_data.a, vec3(0.0));\n\n        vec3 direct_irradiance = texture2D(direct, gl_FragCoord.xy/viewport).rgb * sun_radiance;\n        vec4 diffuse_color = texture2D(albedo, gl_FragCoord.xy/viewport);\n\n        vec3 irradiance = (global_irradiance*gi_factor + direct_irradiance*di_factor)*occlusion;\n        vec3 excident = mix(sky_radiance, diffuse_color.rgb*irradiance, diffuse_color.a);\n        \n        vec4 debug_data = texture2D(debug, gl_FragCoord.xy/viewport);\n        vec3 color = mix(excident, debug_data.rgb, debug_data.a*probe_factor);\n\n        color = brightness * color;\n\n        vec3 luma_coeff = vec3(0.2125, 0.7154, 0.0721);\n        vec3 intensity = vec3(dot(color, luma_coeff));\n        color = mix(intensity, color, saturation);\n        \n        gl_FragColor = vec4(clamp(pow(color, vec3(1.0/gamma)), vec3(0.0), vec3(1.0)), 1.0);\n    }\n"
  },
  {
    "path": "src/deferred_model.coffee",
    "content": "Sphere = require '/webgl/sphere'\n\nreturn class DeferredModel extends require('webgl/drawable')\n    attribs: ['position', 'lightprobe', 'center']\n    pointers: [\n        {name: 'position',    size: 3, offset: 0, stride: 7},\n        {name: 'lightprobe',  size: 4, offset: 3, stride: 7},\n    ]\n    constructor: (@gl, probes) ->\n        super()\n        template = Sphere.makeVertices(5.1, 2)\n\n        buffer = []\n        for probe, i in probes\n            px = probe.x\n            py = probe.y\n            pz = probe.z\n            for vi in [0...template.length] by 3\n                x = template[vi]\n                y = template[vi+1]\n                z = template[vi+2]\n                buffer.push(x,y,z,px,py,pz,i)\n\n        @size = buffer.length/7\n        @uploadList buffer\n"
  },
  {
    "path": "src/deferred_model.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar DeferredModel, Sphere,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nSphere = require('/webgl/sphere');\n\nreturn DeferredModel = (function(_super) {\n\n  __extends(DeferredModel, _super);\n\n  DeferredModel.prototype.attribs = ['position', 'lightprobe', 'center'];\n\n  DeferredModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 7\n    }, {\n      name: 'lightprobe',\n      size: 4,\n      offset: 3,\n      stride: 7\n    }\n  ];\n\n  function DeferredModel(gl, probes) {\n    var buffer, i, probe, px, py, pz, template, vi, x, y, z, _i, _j, _len, _ref;\n    this.gl = gl;\n    DeferredModel.__super__.constructor.call(this);\n    template = Sphere.makeVertices(5.1, 2);\n    buffer = [];\n    for (i = _i = 0, _len = probes.length; _i < _len; i = ++_i) {\n      probe = probes[i];\n      px = probe.x;\n      py = probe.y;\n      pz = probe.z;\n      for (vi = _j = 0, _ref = template.length; _j < _ref; vi = _j += 3) {\n        x = template[vi];\n        y = template[vi + 1];\n        z = template[vi + 2];\n        buffer.push(x, y, z, px, py, pz, i);\n      }\n    }\n    this.size = buffer.length / 7;\n    this.uploadList(buffer);\n  }\n\n  return DeferredModel;\n\n})(require('webgl/drawable'));\n"
  },
  {
    "path": "src/depth/deferred_shadow_map.shader",
    "content": "varying vec2 clip;\n\nvertex:\n    attribute vec2 position;\n\n    void main(){\n        clip = position;\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    #require variance\n    uniform sampler2D eye_normaldepth;\n    uniform mat4 inv_eye_proj, inv_eye_view;\n    uniform vec2 viewport;\n   \n    void main(){\n        vec4 eye_data = texture2D(eye_normaldepth, gl_FragCoord.xy/viewport);\n        vec3 normal = eye_data.xyz;\n        float depth = eye_data.w;\n        vec4 device_pos = inv_eye_proj * vec4(clip, 1.0, 1.0);\n        vec3 eye_normal = normalize(device_pos.xyz);\n        vec3 eye_pos = depth * eye_normal;\n        vec3 position = (inv_eye_view * vec4(eye_pos, 1.0)).xyz;\n\n        gl_FragColor = vec4(vec3(getIntensity(position, normal)), 1.0);\n    }\n"
  },
  {
    "path": "src/depth/depth.shader",
    "content": "varying vec3 vViewPosition;\nuniform mat4 proj, view;\n\nvertex:\n    attribute vec3 position;\n\n    void main(){\n        vViewPosition = (view * vec4(position, 1.0)).xyz;\n        gl_Position = proj * view * vec4(position, 1.0);\n    }\n\nfragment:\n    #extension GL_OES_standard_derivatives : enable\n    uniform float range;\n\n    void main(){\n        float z = -vViewPosition.z/range;\n        float dx = dFdx(z);\n        float dy = dFdy(z);\n        gl_FragColor = vec4(z, z*z + 0.25*(dx*dx + dy*dy), 0.0, 1.0);\n    }\n"
  },
  {
    "path": "src/depth/lightmap_shadow_map.shader",
    "content": "varying vec3 vPosition, vNormal;\n\nvertex:\n    attribute vec3 position, normal;\n    attribute vec2 texcoord;\n\n    void main(){\n        vPosition = position;\n        vNormal = normal;\n        gl_Position = vec4(texcoord*2.0-1.0, 0.0, 1.0);\n    }\n\nfragment:\n    #require variance\n    \n    void main(){\n        gl_FragColor = vec4(vec3(getIntensity(vPosition, normalize(vNormal))), 1.0);\n    }\n"
  },
  {
    "path": "src/depth/module.coffee",
    "content": "Rendernode = require '/rendernode'\nBlur = require '/blur'\n\nexports.DepthRender = class DepthRender\n    constructor: (gl, width, height, drawable, {blurred}={}) ->\n        blurred ?= false\n\n        floatExt = gl.getFloatExtension require: ['renderable', 'filterable']\n\n        @direct = new Rendernode gl,\n            width: width\n            height: height\n            program: get 'depth.shader'\n            drawable: drawable\n            depthBuffer: true\n            depthTest: true\n            depthWrite: true\n            filter: if blurred then 'nearest' else 'linear'\n            #type: gl.FLOAT #float is required because of depth precision\n            type: floatExt.type\n            cullFace: 'BACK'\n       \n        if blurred\n            @blurred = new Blur gl,\n                width: width\n                height: height\n                #type: gl.FLOAT\n                type: floatExt.type\n\n        @output = if @blurred then @blurred.output else @direct\n\n    update: (proj, view) ->\n        @direct.start()\n            .clearBoth(0,0,0,1)\n            .mat4('proj', proj)\n            .mat4('view', view)\n            .f('range', 42) #FIXME\n            .draw()\n            .end()\n\n        if @blurred\n            @blurred.update(@direct)\n\nexports.DeferredShadowMap = class DeferredShadowMap\n    constructor: (gl, {drawable, depthWidth, depthHeight, @eyeNormaldepth, @light, @camera, blurred}) ->\n        @depth = new DepthRender gl, depthWidth, depthHeight, drawable, blurred:blurred\n        @output = new Rendernode gl,\n            program: get 'deferred_shadow_map.shader'\n            drawable: quad\n\n        @updateDepth()\n\n    resize: (width, height) ->\n        @output.resize width, height\n\n    updateDepth: ->\n        @depth.update @light.proj, @light.view\n\n    updateShadow: ->\n        @output\n            .start()\n            .clear(1, 0, 1)\n            .sampler('eye_normaldepth', @eyeNormaldepth)\n            .sampler('light_depth', @depth.output)\n            .mat4('inv_eye_proj', @camera.inv_proj)\n            .mat4('inv_eye_view', @camera.inv_view)\n            .mat4('light_view', @light.view)\n            .mat4('light_proj', @light.proj)\n            .mat3('light_rot', @light.rot)\n            .draw()\n            .end()\n\nexports.LightmapShadowMap = class LightmappedShadowMap\n    constructor: (gl, {drawable, depthWidth, depthHeight, lightmapSize, @light, blurred}) ->\n        @depth = new DepthRender gl, depthWidth, depthHeight, drawable, blurred:blurred\n\n        lightmapSize ?= 256\n\n        @output = new Rendernode gl,\n            width: lightmapSize\n            height: lightmapSize\n            program: get 'lightmap_shadow_map.shader'\n            drawable: drawable\n\n        @update()\n    \n    update: ->\n        @depth.update @light.proj, @light.view\n        @output\n            .start()\n            .sampler('light_depth', @depth.output)\n            .mat4('light_view', @light.view)\n            .mat4('light_proj', @light.proj)\n            .mat3('light_rot', @light.rot)\n            .draw()\n            .end()\n"
  },
  {
    "path": "src/depth/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Blur, DeferredShadowMap, DepthRender, LightmappedShadowMap, Rendernode;\n\nRendernode = require('/rendernode');\n\nBlur = require('/blur');\n\nexports.DepthRender = DepthRender = (function() {\n\n  function DepthRender(gl, width, height, drawable, _arg) {\n    var blurred, floatExt;\n    blurred = (_arg != null ? _arg : {}).blurred;\n    if (blurred == null) {\n      blurred = false;\n    }\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.direct = new Rendernode(gl, {\n      width: width,\n      height: height,\n      program: get('depth.shader'),\n      drawable: drawable,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      filter: blurred ? 'nearest' : 'linear',\n      type: floatExt.type,\n      cullFace: 'BACK'\n    });\n    if (blurred) {\n      this.blurred = new Blur(gl, {\n        width: width,\n        height: height,\n        type: floatExt.type\n      });\n    }\n    this.output = this.blurred ? this.blurred.output : this.direct;\n  }\n\n  DepthRender.prototype.update = function(proj, view) {\n    this.direct.start().clearBoth(0, 0, 0, 1).mat4('proj', proj).mat4('view', view).f('range', 42).draw().end();\n    if (this.blurred) {\n      return this.blurred.update(this.direct);\n    }\n  };\n\n  return DepthRender;\n\n})();\n\nexports.DeferredShadowMap = DeferredShadowMap = (function() {\n\n  function DeferredShadowMap(gl, _arg) {\n    var blurred, depthHeight, depthWidth, drawable;\n    drawable = _arg.drawable, depthWidth = _arg.depthWidth, depthHeight = _arg.depthHeight, this.eyeNormaldepth = _arg.eyeNormaldepth, this.light = _arg.light, this.camera = _arg.camera, blurred = _arg.blurred;\n    this.depth = new DepthRender(gl, depthWidth, depthHeight, drawable, {\n      blurred: blurred\n    });\n    this.output = new Rendernode(gl, {\n      program: get('deferred_shadow_map.shader'),\n      drawable: quad\n    });\n    this.updateDepth();\n  }\n\n  DeferredShadowMap.prototype.resize = function(width, height) {\n    return this.output.resize(width, height);\n  };\n\n  DeferredShadowMap.prototype.updateDepth = function() {\n    return this.depth.update(this.light.proj, this.light.view);\n  };\n\n  DeferredShadowMap.prototype.updateShadow = function() {\n    return this.output.start().clear(1, 0, 1).sampler('eye_normaldepth', this.eyeNormaldepth).sampler('light_depth', this.depth.output).mat4('inv_eye_proj', this.camera.inv_proj).mat4('inv_eye_view', this.camera.inv_view).mat4('light_view', this.light.view).mat4('light_proj', this.light.proj).mat3('light_rot', this.light.rot).draw().end();\n  };\n\n  return DeferredShadowMap;\n\n})();\n\nexports.LightmapShadowMap = LightmappedShadowMap = (function() {\n\n  function LightmappedShadowMap(gl, _arg) {\n    var blurred, depthHeight, depthWidth, drawable, lightmapSize;\n    drawable = _arg.drawable, depthWidth = _arg.depthWidth, depthHeight = _arg.depthHeight, lightmapSize = _arg.lightmapSize, this.light = _arg.light, blurred = _arg.blurred;\n    this.depth = new DepthRender(gl, depthWidth, depthHeight, drawable, {\n      blurred: blurred\n    });\n    if (lightmapSize == null) {\n      lightmapSize = 256;\n    }\n    this.output = new Rendernode(gl, {\n      width: lightmapSize,\n      height: lightmapSize,\n      program: get('lightmap_shadow_map.shader'),\n      drawable: drawable\n    });\n    this.update();\n  }\n\n  LightmappedShadowMap.prototype.update = function() {\n    this.depth.update(this.light.proj, this.light.view);\n    return this.output.start().sampler('light_depth', this.depth.output).mat4('light_view', this.light.view).mat4('light_proj', this.light.proj).mat3('light_rot', this.light.rot).draw().end();\n  };\n\n  return LightmappedShadowMap;\n\n})();\n"
  },
  {
    "path": "src/depth/variance.shaderlib",
    "content": "uniform sampler2D light_depth;\nuniform mat4 light_view, light_proj;\nuniform mat3 light_rot;\n\nfloat getOcclusion(vec2 uv, float z){\n    vec2 moments = texture2D(light_depth, uv).xy;\n    float p = smoothstep(z-0.02, z-0.01, moments.x);\n    float variance = moments.y - moments.x*moments.x;\n    float d = z - moments.x;\n    float p_max = variance/(variance+d*d);\n    p_max = smoothstep(0.4, 1.0, p_max);\n    return max(p, p_max);\n}\n\nfloat getIntensity(vec3 position, vec3 normal){\n        vec4 light_view_position = light_view * vec4(position, 1.0);\n        vec4 light_device = light_proj * light_view_position;\n        vec2 light_clip = light_device.xy/light_device.w;\n        vec2 uv = light_clip*0.5+0.5;\n        float z = -light_view_position.z/42.0;\n        \n        float occlusion = getOcclusion(uv, z);\n        float lambert = clamp((light_rot * normal).z, 0.0, 1.0);\n        return occlusion * lambert;\n}\n        \n        \n\n"
  },
  {
    "path": "src/direct_illumination.shader",
    "content": "varying vec2 clip;\n\nvertex:\n    attribute vec2 position;\n\n    void main(){\n        clip = position;\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D sun_normaldepth, eye_normaldepth;\n    uniform float eye_near, eye_far, sun_near, sun_far;\n    uniform mat4 inv_eye_proj, inv_eye_view, sun_view, sun_proj;\n    uniform mat3 sun_rot, inv_eye_rot;\n    uniform vec2 sun_normaldepth_size;\n    uniform vec2 viewport;\n    uniform float epsilon, shadow_bias, shadow_distance;\n   \n    vec2 getMoments(vec2 uv, float x, float y){\n        vec4 sun_data = texture2D(sun_normaldepth, uv + vec2(x,y)/sun_normaldepth_size);\n        return sun_data.rg;\n    }\n    float linstep(float low, float high, float v){\n        return clamp((v-low)/(high-low), 0.0, 1.0);\n    }\n\n    float occlusionFun(vec2 moments, float z){\n        float p = smoothstep(z-0.02, z-0.01, moments.x);\n        float variance = moments.y - moments.x*moments.x;\n        float d = z - moments.x;\n        float p_max = variance/(variance+d*d);\n        //p_max = linstep(0.4, 1.0, p_max);\n        p_max = smoothstep(0.4, 1.0, p_max);\n        return max(p, p_max);\n    }\n\n    float getOcclusion(vec2 uv, float z, float x, float y){\n        vec2 moments = getMoments(uv, x, y);\n        return occlusionFun(moments, z);\n    }\n\n    void main(){\n        vec4 eye_data = texture2D(eye_normaldepth, gl_FragCoord.xy/viewport);\n        vec3 normal = eye_data.xyz;\n        float depth = eye_data.w;\n        vec4 device_pos = inv_eye_proj * vec4(clip, 1.0, 1.0);\n        vec3 eye_normal = normalize(device_pos.xyz);\n        vec3 eye_pos = depth * eye_normal;\n        vec3 position = (inv_eye_view * vec4(eye_pos, 1.0)).xyz;\n\n        vec4 sun_view_position = sun_view * vec4(position, 1.0);\n        vec4 sun_device = sun_proj * sun_view_position;\n        vec2 sun_clip = sun_device.xy/sun_device.w;\n        vec2 uv = sun_clip*0.5+0.5;\n        float z = -sun_view_position.z/42.0;\n\n        //float occlusion = getOcclusion(uv, z, 0.0, 0.0);\n        float occlusion = getOcclusion(uv, z, 0.0, 0.0);\n        float lambert = clamp((sun_rot * normal).z, 0.0, 1.0);\n        //float intensity = clamp(min(occlusion, lambert), 0.0, 1.0);\n        float intensity = occlusion * lambert;\n        //float intensity = (1.0 - occlusion)*lambert;\n        vec3 color = intensity * vec3(1.0, 0.95, 1.0);\n        gl_FragColor = vec4(color, 1.0);\n        //gl_FragColor = vec4(vec3(occlusion), 1.0);\n    }\n"
  },
  {
    "path": "src/dist3d.coffee",
    "content": "vsub = (p1, p2) ->\n    return [\n        p1[0] - p2[0],\n        p1[1] - p2[1],\n        p1[2] - p2[2],\n    ]\n\nvadd = (p1, p2) ->\n    return [\n        p1[0] + p2[0],\n        p1[1] + p2[1],\n        p1[2] + p2[2],\n    ]\n\nsadd = (s, p) ->\n    x=p[0]; y=p[1]; z=p[2]\n    return [x+s, y+s, z+s]\n\nslength = (p) ->\n    x=p[0]; y=p[1]; z=p[2]\n    return x*x + y*y + z*z\n\nlength = (p) ->\n    return Math.sqrt(slength(p))\n\ndot = (p1, p2) ->\n    x1=p1[0]; y1=p1[1]; z1=p1[2]\n    x2=p2[0]; y2=p2[1]; z2=p2[2]\n    return x1*x2 + y1*y2 + z1*z2\n\nsmul = (s, p) ->\n    x=p[0]; y=p[1]; z=p[2]\n    return [x*s, y*s, z*s]\n\ncross = (p1, p2) ->\n    x1=p1[0]; y1=p1[1]; z1=p1[2]\n    x2=p2[0]; y2=p2[1]; z2=p2[2]\n    \n    return [\n        y1*z2 - z1*y2,\n        z1*x2 - x1*z2,\n        x1*y2 - y1*x2,\n    ]\n\nexports.closestPointTriangle = (p, a, b, c) ->\n    ab = vsub(b, a)\n    ac = vsub(c, a)\n    bc = vsub(c, b)\n\n    snom = dot(vsub(p,a), ab); sdenom = dot(vsub(p,b), vsub(a,b))\n    tnom = dot(vsub(p, a), ac); tdenom = dot(vsub(p,c), vsub(a,c))\n    if snom <= 0 and tnom <= 0 then return a\n\n    unom = dot(vsub(p,b), bc); udenom = dot(vsub(p,c), vsub(b,c))\n    if sdenom <= 0 and unom <= 0 then return b\n    if tdenom <= 0 and udenom <= 0 then return c\n\n    n = cross(vsub(b,a), vsub(c,a))\n    vc = dot(n, cross(vsub(a,p), vsub(b,p)))\n    if vc <= 0 and snom >= 0 and sdenom >= 0\n        return vadd(a, smul(snom/(snom + sdenom), ab))\n\n    va = dot(n, cross(vsub(b,p), vsub(c,p)))\n    if va <= 0 and unom >= 0 and udenom >= 0\n        return vadd(b, smul(unom/(unom + udenom), bc))\n\n    vb = dot(n, cross(vsub(c,p), vsub(a,p)))\n    if vb <= 0 and tnom > 0 and tdenom >= 0\n        return vadd(a, smul(tnom/(tnom + tdenom), ac))\n\n    u = va/(va+vb+vc)\n    v = vb/(va+vb+vc)\n    w = 1-u-v\n    return vadd(smul(u, a), vadd(smul(v,b), smul(w,c)))\n\nexports.pointTriangleDist = (p, v0, v1, v2) ->\n    [cx, cy, cz] = exports.closestPointTriangle(p, v0, v1, v2)\n    [px, py, pz] = p\n    dx=cx-px; dy=cy-py; dz=cz-pz\n    return Math.sqrt(dx*dx + dy*dy + dz*dz)\n"
  },
  {
    "path": "src/dist3d.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar cross, dot, length, sadd, slength, smul, vadd, vsub;\n\nvsub = function(p1, p2) {\n  return [p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]];\n};\n\nvadd = function(p1, p2) {\n  return [p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]];\n};\n\nsadd = function(s, p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return [x + s, y + s, z + s];\n};\n\nslength = function(p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return x * x + y * y + z * z;\n};\n\nlength = function(p) {\n  return Math.sqrt(slength(p));\n};\n\ndot = function(p1, p2) {\n  var x1, x2, y1, y2, z1, z2;\n  x1 = p1[0];\n  y1 = p1[1];\n  z1 = p1[2];\n  x2 = p2[0];\n  y2 = p2[1];\n  z2 = p2[2];\n  return x1 * x2 + y1 * y2 + z1 * z2;\n};\n\nsmul = function(s, p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return [x * s, y * s, z * s];\n};\n\ncross = function(p1, p2) {\n  var x1, x2, y1, y2, z1, z2;\n  x1 = p1[0];\n  y1 = p1[1];\n  z1 = p1[2];\n  x2 = p2[0];\n  y2 = p2[1];\n  z2 = p2[2];\n  return [y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2];\n};\n\nexports.closestPointTriangle = function(p, a, b, c) {\n  var ab, ac, bc, n, sdenom, snom, tdenom, tnom, u, udenom, unom, v, va, vb, vc, w;\n  ab = vsub(b, a);\n  ac = vsub(c, a);\n  bc = vsub(c, b);\n  snom = dot(vsub(p, a), ab);\n  sdenom = dot(vsub(p, b), vsub(a, b));\n  tnom = dot(vsub(p, a), ac);\n  tdenom = dot(vsub(p, c), vsub(a, c));\n  if (snom <= 0 && tnom <= 0) {\n    return a;\n  }\n  unom = dot(vsub(p, b), bc);\n  udenom = dot(vsub(p, c), vsub(b, c));\n  if (sdenom <= 0 && unom <= 0) {\n    return b;\n  }\n  if (tdenom <= 0 && udenom <= 0) {\n    return c;\n  }\n  n = cross(vsub(b, a), vsub(c, a));\n  vc = dot(n, cross(vsub(a, p), vsub(b, p)));\n  if (vc <= 0 && snom >= 0 && sdenom >= 0) {\n    return vadd(a, smul(snom / (snom + sdenom), ab));\n  }\n  va = dot(n, cross(vsub(b, p), vsub(c, p)));\n  if (va <= 0 && unom >= 0 && udenom >= 0) {\n    return vadd(b, smul(unom / (unom + udenom), bc));\n  }\n  vb = dot(n, cross(vsub(c, p), vsub(a, p)));\n  if (vb <= 0 && tnom > 0 && tdenom >= 0) {\n    return vadd(a, smul(tnom / (tnom + tdenom), ac));\n  }\n  u = va / (va + vb + vc);\n  v = vb / (va + vb + vc);\n  w = 1 - u - v;\n  return vadd(smul(u, a), vadd(smul(v, b), smul(w, c)));\n};\n\nexports.pointTriangleDist = function(p, v0, v1, v2) {\n  var cx, cy, cz, dx, dy, dz, px, py, pz, _ref;\n  _ref = exports.closestPointTriangle(p, v0, v1, v2), cx = _ref[0], cy = _ref[1], cz = _ref[2];\n  px = p[0], py = p[1], pz = p[2];\n  dx = cx - px;\n  dy = cy - py;\n  dz = cz - pz;\n  return Math.sqrt(dx * dx + dy * dy + dz * dz);\n};\n"
  },
  {
    "path": "src/global_illumination.shader",
    "content": "\n/*\n    Conclusion of is that the shader is fillrate bound, not lookup bound\n\n    42 fps without GI\n    42 fps when discarding in VS\n    21 fps with unified geometry\n    21 fps with early z and discard\n    21 fps with early z and gl_FragColor write\n    21 fps when discarding in FS\n    17 fps with GI\n    17 fps without discard\n    17 fps without light lookup\n    13 fps without conditional/discard\n*/\n\nvarying vec3 vViewPosition;\nvarying vec4 vLightprobe;\nuniform mat4 proj, view;\nuniform sampler2D normaldepth;\n\nvertex:\n    attribute vec3 position, center;\n    attribute vec4 lightprobe;\n    \n    void main(){\n        vec3 pos = lightprobe.xyz + position;\n        vViewPosition = (view * vec4(pos, 1.0)).xyz;\n        vLightprobe = lightprobe;\n\n        gl_Position = proj * view * vec4(pos, 1.0);\n\n        /* // gives some speed, difficult to get rid of artifacts, very uneven performance\n        vec4 center_view = view * vec4(lightprobe.xyz+center, 1.0);\n        vec4 center_proj = proj * center_view;\n        clip = center_proj.xy/center_proj.w;\n        float scene_depth = texture2D(normaldepth, clip*0.5+0.5).w;\n        float center_depth = length(center_view.xyz);\n        float dist = distance(normalize(center_view.xyz) * scene_depth, (view * vec4(lightprobe.xyz, 1.0)).xyz);\n        if(abs(clip.x) < 1.0 && abs(clip.y) < 1.0 && dist < 5.0){\n\n            gl_Position = proj * view * vec4(pos, 1.0);\n        }\n        else{\n            gl_Position = vec4(2.0);\n        }\n        */\n    }\n\nfragment:\n    #require harmonics\n\n    uniform mat4 inv_view;\n    uniform vec2 viewport;\n    uniform float gi_gain;\n    //uniform float index;\n   \n    void main(){\n        vec4 data = texture2D(normaldepth, gl_FragCoord.xy/viewport);\n        vec3 normal = data.xyz;\n        float depth = data.w;\n        vec3 eye_pos = depth * normalize(vViewPosition);\n        vec3 position = (inv_view * vec4(eye_pos, 1.0)).xyz;\n\n        // apply the global illumination\n        float dist = distance(vLightprobe.xyz, position);\n        float lambert = dot(normal, normalize(vLightprobe.xyz-position));\n        if(dist < 5.0 && lambert > 0.0){\n            float falloff = 1.0 - clamp(dist/5.0, 0.0, 1.0);\n            float intensity = clamp(pow(falloff, 1.5) * lambert, 0.0, 1.0);\n            vec3 irradiance = sphericalHarmonics(vLightprobe.w, normal)*gi_gain;\n            gl_FragColor = vec4(irradiance * intensity, intensity);\n        }\n        else{\n            discard;\n        }\n    }\n"
  },
  {
    "path": "src/harmonics.shaderlib",
    "content": "uniform vec2 coefficients_size;\nuniform sampler2D coefficients;\nuniform float shconst[5];\n\nvec3 getCoefficient(float index, float m){\n    vec2 coord = vec2(m+0.5, index+0.5)/coefficients_size;\n    return texture2D(coefficients, coord).rgb;\n}\n\nvec3 sphericalHarmonics(float index, vec3 normal){\n    float x = normal.x;\n    float y = normal.y;\n    float z = normal.z;\n    \n    vec3 l00 = getCoefficient(index, 0.0);\n    \n    vec3 l10 = getCoefficient(index, 1.0);\n    vec3 l11 = getCoefficient(index, 2.0);\n    vec3 l12 = getCoefficient(index, 3.0);\n\n    vec3 l20 = getCoefficient(index, 4.0);\n    vec3 l21 = getCoefficient(index, 5.0);\n    vec3 l22 = getCoefficient(index, 6.0);\n    vec3 l23 = getCoefficient(index, 7.0);\n    vec3 l24 = getCoefficient(index, 8.0);\n    \n    vec3 result = (\n        l00 * shconst[0] +\n\n        l12 * shconst[1] * x +\n        l10 * shconst[1] * y + \n        l11 * shconst[1] * z +\n\n        l20 * shconst[2] * x*y +\n        l21 * shconst[2] * y*z +\n        l22 * shconst[3] * (3.0*z*z - 1.0) +\n        l23 * shconst[2] * x*z +\n        l24 * shconst[4] * (x*x - y*y)\n    );\n    return max(result, vec3(0.0));\n}\n"
  },
  {
    "path": "src/illumination/bounce.shader",
    "content": "varying vec3 vPosition, vNormal;\nvarying vec4 vLightprobe;\n\nvertex:\n    attribute vec3 position, normal;\n    attribute vec2 texcoord;\n    attribute vec4 lightprobe;\n\n    void main(){\n        vPosition = position;\n        vNormal = normal;\n        vLightprobe = lightprobe;\n        gl_Position = vec4(texcoord*2.0-1.0, 0.0, 1.0);\n    }\n\nfragment:\n    #require /harmonics\n    uniform vec2 viewport;\n    uniform float gi_gain;\n    \n    void main(){\n        // compute world normal\n        vec3 normal = normalize(vNormal);\n\n        // apply the global illumination\n        float dist = distance(vLightprobe.xyz, vPosition);\n        float lambert = dot(normal, normalize(vLightprobe.xyz-vPosition));\n        if(dist < 5.0 && lambert > 0.0){\n            float falloff = 1.0 - clamp(dist/5.0, 0.0, 1.0);\n            float intensity = clamp(pow(falloff, 1.5) * lambert, 0.0, 1.0);\n            vec3 irradiance = sphericalHarmonics(vLightprobe.w, normal)*gi_gain;\n            gl_FragColor = vec4(irradiance * intensity, intensity);\n        }\n        else{\n            discard;\n        }\n    }\n"
  },
  {
    "path": "src/illumination/bounce_model.coffee",
    "content": "{pointTriangleDist} = require '/dist3d'\n\nreturn class BounceModel extends require('/webgl/drawable')\n    attribs: ['position', 'texcoord', 'normal', 'lightprobe']\n    pointers: [\n        {name: 'position', size: 3, offset: 0, stride: 12},\n        {name: 'texcoord', size: 2, offset: 3, stride: 12},\n        {name: 'normal', size: 3, offset: 5, stride: 12},\n        {name: 'lightprobe', size: 4, offset: 8, stride: 12},\n    ]\n\n    constructor: (@gl, model, probes) ->\n        super()\n\n        start = gettime()\n\n        vertices = model.vertices\n        vertex_count = vertices.length/8\n        face_count = vertex_count/3\n\n        result = []\n\n        for i in [0...face_count]\n            verti = i*3\n\n            vali = verti*8\n            x1 = vertices[vali+0]\n            y1 = vertices[vali+1]\n            z1 = vertices[vali+2]\n            u1 = vertices[vali+3]\n            v1 = vertices[vali+4]\n            nx1 = vertices[vali+5]\n            ny1 = vertices[vali+6]\n            nz1 = vertices[vali+7]\n            \n            vali = verti*8+8\n            x2 = vertices[vali+0]\n            y2 = vertices[vali+1]\n            z2 = vertices[vali+2]\n            u2 = vertices[vali+3]\n            v2 = vertices[vali+4]\n            nx2 = vertices[vali+5]\n            ny2 = vertices[vali+6]\n            nz2 = vertices[vali+7]\n            \n            vali = verti*8+16\n            x3 = vertices[vali+0]\n            y3 = vertices[vali+1]\n            z3 = vertices[vali+2]\n            u3 = vertices[vali+3]\n            v3 = vertices[vali+4]\n            nx3 = vertices[vali+5]\n            ny3 = vertices[vali+6]\n            nz3 = vertices[vali+7]\n            for probe, i in probes\n                px = probe.x; py = probe.y; pz = probe.z\n\n                dx1 = px-x1; dy1 = py-y1; dz1 = pz-z1\n                l = Math.sqrt(dx1*dx1+dy1*dy1+dz1*dz1)\n                dx1/=l; dy1/=l; dz1/=l\n                dot1 = dx1*nx1 + dy1*ny1 + dz1*nz1\n                \n                dx2 = px-x2; dy2 = py-y2; dz2 = pz-z2\n                l = Math.sqrt(dx2*dx2+dy2*dy2+dz2*dz2)\n                dx2/=l; dy2/=l; dz2/=l\n                dot2 = dx2*nx2 + dy2*ny2 + dz2*nz2\n                \n                dx3 = px-x3; dy3 = py-y3; dz3 = pz-z3\n                l = Math.sqrt(dx3*dx3+dy3*dy3+dz3*dz3)\n                dx3/=l; dy3/=l; dz3/=l\n                dot3 = dx3*nx3 + dy3*ny3 + dz3*nz3\n            \n                \n                # triangle plane\n                tx=x2-x1; ty=y2-y1; tz=z2-z1\n                btx=x3-x1; bty=y3-y1; btz=z3-z1\n\n                fnx = ty*btz - tz*bty\n                fny = tz*btx - tx*btz\n                fnz = tx*bty - ty*btx\n                l = Math.sqrt(fnx*fnx + fny*fny + fnz*fnz)\n                fnx/=l; fny/=l; fnz/=l\n                det = fnx*x1 + fny*y1 + fnz*z1\n                dist = Math.abs((fnx*px + fny*py + fnz*pz)-det)\n\n                if (dot1 >= 0 or dot2 >= 0 or dot3 >= 0) and dist <= 5.0\n                    if pointTriangleDist([px, py, pz], [x1, y1, z1], [x2, y2, z2], [x3, y3, z3]) <= 5.0\n                        result.push(\n                            x1, y1, z1, u1, v1, nx1, ny1, nz1, px, py, pz, i,\n                            x2, y2, z2, u2, v2, nx2, ny2, nz2, px, py, pz, i,\n                            x3, y3, z3, u3, v3, nx3, ny3, nz3, px, py, pz, i,\n                        )\n\n        #console.log (result.length/12)/((vertices.length/8)*probes.length)\n        @size = result.length/12\n        @uploadList result\n        #console.log gettime() - start\n\n"
  },
  {
    "path": "src/illumination/bounce_model.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar BounceModel, pointTriangleDist,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\npointTriangleDist = require('/dist3d').pointTriangleDist;\n\nreturn BounceModel = (function(_super) {\n\n  __extends(BounceModel, _super);\n\n  BounceModel.prototype.attribs = ['position', 'texcoord', 'normal', 'lightprobe'];\n\n  BounceModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 12\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 12\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 12\n    }, {\n      name: 'lightprobe',\n      size: 4,\n      offset: 8,\n      stride: 12\n    }\n  ];\n\n  function BounceModel(gl, model, probes) {\n    var btx, bty, btz, det, dist, dot1, dot2, dot3, dx1, dx2, dx3, dy1, dy2, dy3, dz1, dz2, dz3, face_count, fnx, fny, fnz, i, l, nx1, nx2, nx3, ny1, ny2, ny3, nz1, nz2, nz3, probe, px, py, pz, result, start, tx, ty, tz, u1, u2, u3, v1, v2, v3, vali, vertex_count, verti, vertices, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i, _j, _len;\n    this.gl = gl;\n    BounceModel.__super__.constructor.call(this);\n    start = gettime();\n    vertices = model.vertices;\n    vertex_count = vertices.length / 8;\n    face_count = vertex_count / 3;\n    result = [];\n    for (i = _i = 0; 0 <= face_count ? _i < face_count : _i > face_count; i = 0 <= face_count ? ++_i : --_i) {\n      verti = i * 3;\n      vali = verti * 8;\n      x1 = vertices[vali + 0];\n      y1 = vertices[vali + 1];\n      z1 = vertices[vali + 2];\n      u1 = vertices[vali + 3];\n      v1 = vertices[vali + 4];\n      nx1 = vertices[vali + 5];\n      ny1 = vertices[vali + 6];\n      nz1 = vertices[vali + 7];\n      vali = verti * 8 + 8;\n      x2 = vertices[vali + 0];\n      y2 = vertices[vali + 1];\n      z2 = vertices[vali + 2];\n      u2 = vertices[vali + 3];\n      v2 = vertices[vali + 4];\n      nx2 = vertices[vali + 5];\n      ny2 = vertices[vali + 6];\n      nz2 = vertices[vali + 7];\n      vali = verti * 8 + 16;\n      x3 = vertices[vali + 0];\n      y3 = vertices[vali + 1];\n      z3 = vertices[vali + 2];\n      u3 = vertices[vali + 3];\n      v3 = vertices[vali + 4];\n      nx3 = vertices[vali + 5];\n      ny3 = vertices[vali + 6];\n      nz3 = vertices[vali + 7];\n      for (i = _j = 0, _len = probes.length; _j < _len; i = ++_j) {\n        probe = probes[i];\n        px = probe.x;\n        py = probe.y;\n        pz = probe.z;\n        dx1 = px - x1;\n        dy1 = py - y1;\n        dz1 = pz - z1;\n        l = Math.sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1);\n        dx1 /= l;\n        dy1 /= l;\n        dz1 /= l;\n        dot1 = dx1 * nx1 + dy1 * ny1 + dz1 * nz1;\n        dx2 = px - x2;\n        dy2 = py - y2;\n        dz2 = pz - z2;\n        l = Math.sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);\n        dx2 /= l;\n        dy2 /= l;\n        dz2 /= l;\n        dot2 = dx2 * nx2 + dy2 * ny2 + dz2 * nz2;\n        dx3 = px - x3;\n        dy3 = py - y3;\n        dz3 = pz - z3;\n        l = Math.sqrt(dx3 * dx3 + dy3 * dy3 + dz3 * dz3);\n        dx3 /= l;\n        dy3 /= l;\n        dz3 /= l;\n        dot3 = dx3 * nx3 + dy3 * ny3 + dz3 * nz3;\n        tx = x2 - x1;\n        ty = y2 - y1;\n        tz = z2 - z1;\n        btx = x3 - x1;\n        bty = y3 - y1;\n        btz = z3 - z1;\n        fnx = ty * btz - tz * bty;\n        fny = tz * btx - tx * btz;\n        fnz = tx * bty - ty * btx;\n        l = Math.sqrt(fnx * fnx + fny * fny + fnz * fnz);\n        fnx /= l;\n        fny /= l;\n        fnz /= l;\n        det = fnx * x1 + fny * y1 + fnz * z1;\n        dist = Math.abs((fnx * px + fny * py + fnz * pz) - det);\n        if ((dot1 >= 0 || dot2 >= 0 || dot3 >= 0) && dist <= 5.0) {\n          if (pointTriangleDist([px, py, pz], [x1, y1, z1], [x2, y2, z2], [x3, y3, z3]) <= 5.0) {\n            result.push(x1, y1, z1, u1, v1, nx1, ny1, nz1, px, py, pz, i, x2, y2, z2, u2, v2, nx2, ny2, nz2, px, py, pz, i, x3, y3, z3, u3, v3, nx3, ny3, nz3, px, py, pz, i);\n          }\n        }\n      }\n    }\n    this.size = result.length / 12;\n    this.uploadList(result);\n  }\n\n  return BounceModel;\n\n})(require('/webgl/drawable'));\n"
  },
  {
    "path": "src/illumination/cube_diffuse.shader",
    "content": "varying vec2 vTexcoord;\nvarying vec3 vPosition;\nuniform mat4 proj, view;\n\nvertex:\n    attribute vec3 position;\n    attribute vec2 texcoord;\n\n    void main(){\n        vTexcoord = texcoord;\n        vPosition = position;\n        gl_Position = proj * view * vec4(position, 1.0);\n    }\n\nfragment:\n    uniform sampler2D diffuse_texture;\n    uniform vec3 diffuse_color;\n    void main(){\n        vec3 diffuse = pow(texture2D(diffuse_texture, vTexcoord).rgb, vec3(1.8));\n        gl_FragColor = vec4(diffuse*pow(diffuse_color, vec3(1.8)), 1.0);\n    }\n"
  },
  {
    "path": "src/illumination/cubeprobe.shader",
    "content": "varying vec2 vTexcoord;\nvarying vec3 vPosition;\nuniform mat4 proj, view;\n\nvertex:\n    attribute vec3 position;\n    attribute vec2 texcoord;\n\n    void main(){\n        vTexcoord = texcoord;\n        vPosition = position;\n        gl_Position = proj * view * vec4(position, 1.0);\n    }\n\nfragment:\n    void main(){\n        gl_FragColor = vec4(vTexcoord, 0.0, 1.0);\n    }\n"
  },
  {
    "path": "src/illumination/debug.shader",
    "content": "varying vec3 vPosition, vViewPosition;\nuniform mat4 proj, view;\n\nvertex:\n    attribute vec3 position;\n    uniform vec3 offset;\n\n    void main(){\n        vPosition = position;\n        vViewPosition = (view * vec4(position+offset, 1.0)).xyz;\n        gl_Position = proj * view * vec4(position+offset, 1.0);\n    }\n\nfragment:\n    #require /harmonics\n    uniform sampler2D normaldepth;\n    uniform vec2 viewport;\n    uniform float gi_gain;\n    uniform float index;\n    \n    void main(){\n        vec4 data = texture2D(normaldepth, gl_FragCoord.xy/viewport);\n        float depth = data.w;\n        if(length(vViewPosition) < depth){\n            gl_FragColor = vec4(sphericalHarmonics(index, normalize(vPosition))*gi_gain, 1.0);\n        }\n        else{\n            discard;\n        }\n    }\n"
  },
  {
    "path": "src/illumination/harmonics.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D lightprobes;\n    uniform vec2 lightprobes_size;\n    uniform float shconst[5];\n    \n    float pi = 3.141592653589793;\n    \n    mat3 front = mat3(\n         1.0,  0.0,  0.0,\n         0.0,  1.0,  0.0,\n         0.0,  0.0,  1.0\n    );\n    \n    mat3 back = mat3(\n        -1.0,  0.0,  0.0,\n         0.0,  1.0,  0.0,\n         0.0,  0.0, -1.0\n    );\n    \n    mat3 left = mat3(\n         0.0,  0.0, -1.0,\n         0.0,  1.0,  0.0,\n         1.0,  0.0,  0.0\n    );\n    \n    mat3 right = mat3(\n         0.0,  0.0,  1.0,\n         0.0,  1.0,  0.0,\n        -1.0,  0.0,  0.0\n    );\n    \n    mat3 up = mat3(\n         1.0,  0.0,  0.0,\n         0.0,  0.0,  1.0,\n         0.0, -1.0,  0.0\n    );\n    \n    mat3 down = mat3(\n         1.0,  0.0,  0.0,\n         0.0,  0.0, -1.0,\n         0.0,  1.0,  0.0\n    );\n\n    float harmonics(vec3 normal){\n        int index = int(gl_FragCoord.x);\n\n        float x = normal.x;\n        float y = normal.y;\n        float z = normal.z;\n      \n        /*\n        if(index==0){\n            return shconst[0];\n        }\n        else if(index==1){\n            return shconst[1] * y;\n        }\n        else if(index==2){\n            return shconst[1] * z;\n        }\n        else if(index==3){\n            return shconst[1] * x;\n        }\n        else if(index==4){\n            return shconst[2]*x*y;\n        }\n        else if(index==5){\n            return shconst[2]*y*z;\n        }\n        else if(index==6){\n            return shconst[3] * (3.0*z*z - 1.0);\n        }\n        else if(index==7){\n            return shconst[2]*x*z;\n        }\n        else{\n            return shconst[4]*(x*x - y*y);\n        }\n        */\n        if(index==0){\n            return 1.0;\n        }\n        else if(index==1){\n            return y;\n        }\n        else if(index==2){\n            return z;\n        }\n        else if(index==3){\n            return x;\n        }\n        else if(index==4){\n            return x*y;\n        }\n        else if(index==5){\n            return y*z;\n        }\n        else if(index==6){\n            return 3.0*z*z - 1.0;\n        }\n        else if(index==7){\n            return x*z;\n        }\n        else{\n            return x*x - y*y;\n        }\n    }\n\n    #define probe_size 16\n\n    vec3 sampleSide(float side, mat3 rot){\n        vec3 result = vec3(0.0);\n\n        float divider = 0.0;\n        //(140,6): error X3511: unable to unroll loop, loop does not appear to terminate in a timely manner (9 iterations), use the [unroll(n)] attribute to force an exact higher number\n        /*\n        for(int y=0; y<probe_size; y++){\n            for(int x=0; x<probe_size; x++){\n                vec2 texcoord = (vec2(float(x)+side*16.0, float(y)+floor(gl_FragCoord.y)*16.0)+0.5)/lightprobes_size;\n                vec2 sidecoord = ((vec2(x,y)+vec2(0.5, 0.5))/vec2(probe_size))*2.0-1.0;\n                vec3 normal = normalize(vec3(sidecoord, -1.0));\n                vec3 texel = texture2D(lightprobes, texcoord).rgb;\n                result += harmonics(rot*normal) * texel * -normal.z;\n                divider += -normal.z;\n            }\n        }\n        */\n        for(int i=0; i<256; i++){\n            float x = mod(float(i), 16.0);\n            float y = float(i/16);\n            vec2 texcoord = (vec2(x+side*16.0, y+floor(gl_FragCoord.y)*16.0)+0.5)/lightprobes_size;\n            vec2 sidecoord = ((vec2(x,y)+vec2(0.5, 0.5))/vec2(16.0))*2.0-1.0;\n            vec3 normal = normalize(vec3(sidecoord, -1.0));\n            vec3 texel = texture2D(lightprobes, texcoord).rgb;\n            result += harmonics(rot*normal) * texel * -normal.z;\n            divider += -normal.z;\n        }\n        return result / divider;\n    }\n    \n    void main(){\n        vec3 result = (\n            sampleSide(0.0, front) +\n            sampleSide(1.0, back) +\n            sampleSide(2.0, left) +\n            sampleSide(3.0, right) +\n            sampleSide(4.0, up) +\n            sampleSide(5.0, down)\n        )/6.0;\n        gl_FragColor = vec4(result, 1.0);\n    }\n"
  },
  {
    "path": "src/illumination/module.coffee",
    "content": "Quad = require '/webgl/quad'\nSphere = require '/webgl/sphere'\n{Texture2D} = require '/webgl/texture'\n\nRendernode = require '/rendernode'\n\n{DepthRender, LightmapShadowMap} = require '/depth'\nBounceModel = require 'bounce_model'\n    \nreturn class Illumination\n    constructor: (@gl, sun, @lighting, model, highresmodel, normaldepth, orientation, elevation, @shconst) ->\n        @proj = new Mat4().perspective(90, 1, 0.01, 42)\n        @view = new Mat4()\n\n        @mapsize = 32\n        @probesize = 16\n\n        @generateProbes()\n\n        floatExt = @gl.getFloatExtension require: ['renderable', 'filterable']\n        \n        @debug = new Rendernode @gl,\n            program: get 'debug.shader'\n            drawable: new Sphere @gl, 0.6\n            depthBuffer: true\n            depthTest: true\n            depthWrite: true\n            cullFace: 'BACK'\n            #type: @gl.FLOAT #maybe, not really essential to scene quality\n            type: floatExt.type\n        \n        @lightprobes = new Rendernode @gl,\n            width: @probesize*6\n            height: @probesize*@probes.length\n            program: get 'transfer.shader'\n            drawable: quad\n            filter: 'nearest'\n            #type: @gl.FLOAT #float is required due to HDR, maybe could solve this with color packing\n            type: floatExt.type\n\n        @coefficients = new Rendernode @gl,\n            width: 9\n            height: @probes.length\n            program: get 'harmonics.shader'\n            drawable: quad\n            filter: 'nearest'\n            #type: @gl.FLOAT #float is required, otherwise bad banding and wrong colors, maybe could solve this with color packing\n            type: floatExt.type\n        \n        @direct_light = new LightmapShadowMap gl,\n            drawable: model\n            depthWidth: 128\n            depthHeight: 128\n            light: sun\n            blurred: true\n\n        @bounce = new Rendernode @gl,\n            width: 256\n            height: 256\n            program: get 'bounce.shader'\n            drawable: new BounceModel @gl, model, @probes\n            #type: @gl.FLOAT #float is required due to additive blending\n            type: floatExt.type\n            blend: 'additive'\n\n        @renderProbes(model, highresmodel)\n        @update()\n\n    generateProbes: () ->\n        @probes = []\n        for i in [0...7]\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 2.2\n                z: 0\n\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 2.2\n                z: 5.5\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 2.2\n                z: -5.5\n\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 7.0\n                z: 0\n            \n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 7.0\n                z: 5.5\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 7.0\n                z: -5.5\n\n        for i in [1...6]\n            @probes.push\n                x: i*4.5 - 3*4.5\n                y: 12.5\n                z: 0\n    \n    updateDirectLight: ->\n        @direct_light.update()\n\n    update: () ->\n        @bounce.start()\n            .clear(0, 0, 0, 1)\n            .f('gi_gain', @lighting.giGain)\n            .val2('coefficients_size', @coefficients.width, @coefficients.height)\n            .fv('shconst', @shconst.data)\n            .end()\n\n        @lightprobes\n            .start()\n            .vec3('sun_radiance', @lighting.sun_radiance)\n            .vec3('sky_radiance', @lighting.sky_radiance)\n            .sampler('texmap', @texmap)\n            .sampler('diffusemap', @diffusemap)\n            .sampler('bounce', @bounce)\n            .sampler('lightmap', @direct_light.output)\n            .draw()\n            .end()\n\n        @coefficients\n            .start()\n            .val2('lightprobes_size', @lightprobes.width, @lightprobes.height)\n            .sampler('lightprobes', @lightprobes)\n            .fv('shconst', @shconst.data)\n            .draw()\n            .end()\n\n        for i in [0...@lighting.bounces-1]\n            @bounce\n                .start()\n                .clear(0, 0, 0, 0)\n                .sampler('coefficients', @coefficients)\n                .draw()\n                .end()\n            \n            @lightprobes\n                .start()\n                .sampler('texmap', @texmap)\n                .sampler('bounce', @bounce)\n                .sampler('lightmap', @direct_light.output)\n                .draw()\n                .end()\n\n            @coefficients\n                .start()\n                .val2('lightprobes_size', @lightprobes.width, @lightprobes.height)\n                .sampler('lightprobes', @lightprobes)\n                .draw()\n                .end()\n\n\n    renderProbes: (model, highresmodel) ->\n        if get.exists 'texmap.png'\n            @texmap = new Texture2D(@gl)\n                .bind()\n                .upload(get 'texmap.png')\n                .nearest()\n                .clampToEdge()\n                .unbind()\n        else\n            @texmap = new Rendernode @gl,\n                width: @mapsize*6\n                height: @mapsize*@probes.length\n                program: get 'cubeprobe.shader'\n                drawable: model\n                depthTest: true\n                depthWrite: true\n                cullFace: 'BACK'\n                filter: 'nearest'\n                depthBuffer: true\n\n            @texmap.start().clear(0, 0, 1)\n            @texmap.mat4('proj', @proj)\n            for probe, i in @probes\n                @renderProbe(i, @texmap, null, probe.x, probe.y, probe.z)\n            @texmap.end()\n            @texmap = @texmap.output\n\n        if get.exists 'diffusemap.jpg'\n            @diffusemap = new Texture2D(@gl)\n                .bind()\n                .upload(get 'diffusemap.jpg')\n                .nearest()\n                .clampToEdge()\n                .unbind()\n        else\n            @diffusemap = new Rendernode @gl,\n                width: @mapsize*6\n                height: @mapsize*@probes.length\n                program: get 'cube_diffuse.shader'\n                drawable: highresmodel\n                depthTest: true\n                depthWrite: true\n                cullFace: 'BACK'\n                filter: 'nearest'\n                depthBuffer: true\n\n            @diffusemap.start().clear(0, 0, 0)\n            @diffusemap.mat4('proj', @proj)\n            for probe, i in @probes\n                @renderProbe(i, @diffusemap, 'diffuse_texture', probe.x, probe.y, probe.z)\n            @diffusemap.end()\n            @diffusemap = @diffusemap.output\n\n        #url = getURL @texmap.output.read().buffer\n        #$('<a download=\"texmap.bin\">texmap</a>').appendTo('#ui')[0].href = url\n        #url = getURL @diffusemap.output.read().buffer\n        #$('<a download=\"diffusemap.bin\">texmap</a>').appendTo('#ui')[0].href = url\n\n    renderProbe: (i, node, texture_type, x, y, z) ->\n        s = @mapsize\n        offset = i*s\n\n        @view.identity().translateVal3(-x, -y, -z)\n        node.viewport(s*0, offset, s, s).mat4('view', @view).drawModel(texture_type)\n\n        @view.identity().rotatey(180).translateVal3(-x, -y, -z)\n        node.viewport(s*1, offset, s, s).mat4('view', @view).drawModel(texture_type)\n\n        @view.identity().rotatey(-90).translateVal3(-x, -y, -z)\n        node.viewport(s*2, offset, s, s).mat4('view', @view).drawModel(texture_type)\n        \n        @view.identity().rotatey(90).translateVal3(-x, -y, -z)\n        node.viewport(s*3, offset, s, s).mat4('view', @view).drawModel(texture_type)\n        \n        @view.identity().rotatex(-90).translateVal3(-x, -y, -z)\n        node.viewport(s*4, offset, s, s).mat4('view', @view).drawModel(texture_type)\n        \n        @view.identity().rotatex(90).translateVal3(-x, -y, -z)\n        node.viewport(s*5, offset, s, s).mat4('view', @view).drawModel(texture_type)\n\n    drawDebug: (camera, normaldepth) ->\n        @debug.start()\n            .clearBoth(0, 0, 0, 0)\n            .f('gi_gain', @lighting.giGain)\n            .sampler('normaldepth', normaldepth)\n            .sampler('coefficients', @coefficients)\n            .val2('coefficients_size', @coefficients.width, @coefficients.height)\n            .fv('shconst', @shconst.data)\n            .mat4('proj', camera.proj)\n            .mat4('view', camera.view)\n\n        for probe, i in @probes\n            @debug\n                .val3('offset', probe.x, probe.y, probe.z)\n                .f('index', i)\n                .draw()\n\n        @debug.end()\n"
  },
  {
    "path": "src/illumination/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar BounceModel, DepthRender, Illumination, LightmapShadowMap, Quad, Rendernode, Sphere, Texture2D, _ref;\n\nQuad = require('/webgl/quad');\n\nSphere = require('/webgl/sphere');\n\nTexture2D = require('/webgl/texture').Texture2D;\n\nRendernode = require('/rendernode');\n\n_ref = require('/depth'), DepthRender = _ref.DepthRender, LightmapShadowMap = _ref.LightmapShadowMap;\n\nBounceModel = require('bounce_model');\n\nreturn Illumination = (function() {\n\n  function Illumination(gl, sun, lighting, model, highresmodel, normaldepth, orientation, elevation, shconst) {\n    var floatExt;\n    this.gl = gl;\n    this.lighting = lighting;\n    this.shconst = shconst;\n    this.proj = new Mat4().perspective(90, 1, 0.01, 42);\n    this.view = new Mat4();\n    this.mapsize = 32;\n    this.probesize = 16;\n    this.generateProbes();\n    floatExt = this.gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.debug = new Rendernode(this.gl, {\n      program: get('debug.shader'),\n      drawable: new Sphere(this.gl, 0.6),\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      cullFace: 'BACK',\n      type: floatExt.type\n    });\n    this.lightprobes = new Rendernode(this.gl, {\n      width: this.probesize * 6,\n      height: this.probesize * this.probes.length,\n      program: get('transfer.shader'),\n      drawable: quad,\n      filter: 'nearest',\n      type: floatExt.type\n    });\n    this.coefficients = new Rendernode(this.gl, {\n      width: 9,\n      height: this.probes.length,\n      program: get('harmonics.shader'),\n      drawable: quad,\n      filter: 'nearest',\n      type: floatExt.type\n    });\n    this.direct_light = new LightmapShadowMap(gl, {\n      drawable: model,\n      depthWidth: 128,\n      depthHeight: 128,\n      light: sun,\n      blurred: true\n    });\n    this.bounce = new Rendernode(this.gl, {\n      width: 256,\n      height: 256,\n      program: get('bounce.shader'),\n      drawable: new BounceModel(this.gl, model, this.probes),\n      type: floatExt.type,\n      blend: 'additive'\n    });\n    this.renderProbes(model, highresmodel);\n    this.update();\n  }\n\n  Illumination.prototype.generateProbes = function() {\n    var i, _i, _j, _results;\n    this.probes = [];\n    for (i = _i = 0; _i < 7; i = ++_i) {\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: 0\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: 5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: -5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: 0\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: 5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: -5.5\n      });\n    }\n    _results = [];\n    for (i = _j = 1; _j < 6; i = ++_j) {\n      _results.push(this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 12.5,\n        z: 0\n      }));\n    }\n    return _results;\n  };\n\n  Illumination.prototype.updateDirectLight = function() {\n    return this.direct_light.update();\n  };\n\n  Illumination.prototype.update = function() {\n    var i, _i, _ref1, _results;\n    this.bounce.start().clear(0, 0, 0, 1).f('gi_gain', this.lighting.giGain).val2('coefficients_size', this.coefficients.width, this.coefficients.height).fv('shconst', this.shconst.data).end();\n    this.lightprobes.start().vec3('sun_radiance', this.lighting.sun_radiance).vec3('sky_radiance', this.lighting.sky_radiance).sampler('texmap', this.texmap).sampler('diffusemap', this.diffusemap).sampler('bounce', this.bounce).sampler('lightmap', this.direct_light.output).draw().end();\n    this.coefficients.start().val2('lightprobes_size', this.lightprobes.width, this.lightprobes.height).sampler('lightprobes', this.lightprobes).fv('shconst', this.shconst.data).draw().end();\n    _results = [];\n    for (i = _i = 0, _ref1 = this.lighting.bounces - 1; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {\n      this.bounce.start().clear(0, 0, 0, 0).sampler('coefficients', this.coefficients).draw().end();\n      this.lightprobes.start().sampler('texmap', this.texmap).sampler('bounce', this.bounce).sampler('lightmap', this.direct_light.output).draw().end();\n      _results.push(this.coefficients.start().val2('lightprobes_size', this.lightprobes.width, this.lightprobes.height).sampler('lightprobes', this.lightprobes).draw().end());\n    }\n    return _results;\n  };\n\n  Illumination.prototype.renderProbes = function(model, highresmodel) {\n    var i, probe, _i, _j, _len, _len1, _ref1, _ref2;\n    if (get.exists('texmap.png')) {\n      this.texmap = new Texture2D(this.gl).bind().upload(get('texmap.png')).nearest().clampToEdge().unbind();\n    } else {\n      this.texmap = new Rendernode(this.gl, {\n        width: this.mapsize * 6,\n        height: this.mapsize * this.probes.length,\n        program: get('cubeprobe.shader'),\n        drawable: model,\n        depthTest: true,\n        depthWrite: true,\n        cullFace: 'BACK',\n        filter: 'nearest',\n        depthBuffer: true\n      });\n      this.texmap.start().clear(0, 0, 1);\n      this.texmap.mat4('proj', this.proj);\n      _ref1 = this.probes;\n      for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {\n        probe = _ref1[i];\n        this.renderProbe(i, this.texmap, null, probe.x, probe.y, probe.z);\n      }\n      this.texmap.end();\n      this.texmap = this.texmap.output;\n    }\n    if (get.exists('diffusemap.jpg')) {\n      return this.diffusemap = new Texture2D(this.gl).bind().upload(get('diffusemap.jpg')).nearest().clampToEdge().unbind();\n    } else {\n      this.diffusemap = new Rendernode(this.gl, {\n        width: this.mapsize * 6,\n        height: this.mapsize * this.probes.length,\n        program: get('cube_diffuse.shader'),\n        drawable: highresmodel,\n        depthTest: true,\n        depthWrite: true,\n        cullFace: 'BACK',\n        filter: 'nearest',\n        depthBuffer: true\n      });\n      this.diffusemap.start().clear(0, 0, 0);\n      this.diffusemap.mat4('proj', this.proj);\n      _ref2 = this.probes;\n      for (i = _j = 0, _len1 = _ref2.length; _j < _len1; i = ++_j) {\n        probe = _ref2[i];\n        this.renderProbe(i, this.diffusemap, 'diffuse_texture', probe.x, probe.y, probe.z);\n      }\n      this.diffusemap.end();\n      return this.diffusemap = this.diffusemap.output;\n    }\n  };\n\n  Illumination.prototype.renderProbe = function(i, node, texture_type, x, y, z) {\n    var offset, s;\n    s = this.mapsize;\n    offset = i * s;\n    this.view.identity().translateVal3(-x, -y, -z);\n    node.viewport(s * 0, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(180).translateVal3(-x, -y, -z);\n    node.viewport(s * 1, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(-90).translateVal3(-x, -y, -z);\n    node.viewport(s * 2, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(90).translateVal3(-x, -y, -z);\n    node.viewport(s * 3, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatex(-90).translateVal3(-x, -y, -z);\n    node.viewport(s * 4, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatex(90).translateVal3(-x, -y, -z);\n    return node.viewport(s * 5, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n  };\n\n  Illumination.prototype.drawDebug = function(camera, normaldepth) {\n    var i, probe, _i, _len, _ref1;\n    this.debug.start().clearBoth(0, 0, 0, 0).f('gi_gain', this.lighting.giGain).sampler('normaldepth', normaldepth).sampler('coefficients', this.coefficients).val2('coefficients_size', this.coefficients.width, this.coefficients.height).fv('shconst', this.shconst.data).mat4('proj', camera.proj).mat4('view', camera.view);\n    _ref1 = this.probes;\n    for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {\n      probe = _ref1[i];\n      this.debug.val3('offset', probe.x, probe.y, probe.z).f('index', i).draw();\n    }\n    return this.debug.end();\n  };\n\n  return Illumination;\n\n})();\n"
  },
  {
    "path": "src/illumination/shadow.shader",
    "content": "varying vec2 vTexcoord;\nvarying vec3 vPosition, vNormal;\nvarying vec3 vViewPosition;\n\nvertex:\n    attribute vec3 position, normal;\n    attribute vec2 texcoord;\n\n    void main(){\n        vTexcoord = texcoord;\n        vPosition = position;\n        vNormal = normal;\n        gl_Position = vec4(texcoord*2.0-1.0, 0.0, 1.0);\n    }\n\nfragment:\n    uniform mat4 shadow_view, shadow_proj;\n    uniform mat3 shadow_rot;\n    uniform sampler2D depth;\n    \n    void main(){\n        vec3 normal = normalize(vNormal);\n        \n        vec4 shadow_view = shadow_view * vec4(vPosition, 1.0);\n        vec4 shadow_device = shadow_proj * shadow_view;\n        vec2 shadow_coord = (shadow_device.xy/shadow_device.w)*0.5+0.5;\n\n        float occlusion = 0.0;\n\n        for(int u=-2; u<=2; u++){\n            for(int v=-2; v<=2; v++){\n                vec4 shadow_value = texture2D(depth, shadow_coord+vec2(u,v)/2048.0);\n                float shadow_depth = shadow_value.w;\n                vec3 shadow_normal = normalize(shadow_value.xyz);\n                float diff = shadow_view.z - shadow_value.w;\n                float shadowed = smoothstep(-0.04, -0.02, diff);\n                occlusion += shadowed;\n            }\n        }\n        occlusion /= 25.0;\n        //float lambert = step(0.01, (shadow_rot * normal).z);\n        float lambert = clamp((shadow_rot * normal).z, 0.0, 1.0);\n        float intensity = min(occlusion, lambert);\n        //float intensity = occlusion*lambert;\n        vec3 color = intensity * vec3(1.0, 0.95, 1.0);\n        gl_FragColor = vec4(color, 1.0);\n    }\n"
  },
  {
    "path": "src/illumination/transfer.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D lightmap, bounce, texmap, diffusemap;\n    uniform vec2 viewport;\n    uniform vec3 sun_radiance, sky_radiance;\n\n    vec3 get(float x, float y){\n        vec2 coord = (gl_FragCoord.xy+vec2(x,y))/viewport;\n        vec3 uv = texture2D(texmap, coord).xyz;\n        if(uv.b > 0.0){\n            return sky_radiance;\n        }\n        else{\n            vec3 diffuse_color = texture2D(diffusemap, coord).rgb;\n            vec4 bounce_data = texture2D(bounce, uv.xy);\n            vec3 direct_irradiance = texture2D(lightmap, uv.xy).rgb*sun_radiance;\n            vec3 global_irradiance = bounce_data.rgb/bounce_data.a;\n            return diffuse_color * (direct_irradiance + global_irradiance);\n        }\n    }\n    void main(){\n        vec3 result = (\n            get(-0.5, -0.5) +\n            get(0.5, 0.5) +\n            get(-0.5, 0.5) +\n            get(0.5, -0.5)\n        )/4.0;\n        gl_FragColor = vec4(max(result, vec3(0.0)), 1.0);\n    }\n        \n"
  },
  {
    "path": "src/main.coffee",
    "content": "audio = require 'audio'\nloading = require 'loading'\nShader = require 'webgl/shader'\nQuad = require 'webgl/quad'\nrequire 'webgl-nuke-vendor-prefix'\nrequire 'webgl-texture-float-extension-shims'\n\n#crashes firefox\n#worker = new Worker('worker.js')\n#worker.postMessage('Ping')\n#worker.onmessage = (event) ->\n#    console.log event\n\nload_hooks =\n    '\\.jpg$|\\.jpeg$|\\.gif$|\\.png': (name, buffer, callback) ->\n        ext =name.split('.').pop()\n        switch ext\n            when 'png' then mime = 'image/png'\n            when 'gif' then mime = 'image/gif'\n            when 'jpg', 'jpeg' then mime = 'image/jpeg'\n                \n        image = new Image()\n        image.src = getURL(buffer, mime)\n        image.onload = ->\n            callback image\n    '\\.mpg$|\\.ogg$|\\.wav$': (name, buffer, callback) ->\n        audio.decode buffer, (result) ->\n            callback result\n\nerrorContainer = (title) ->\n    canvas.remove()\n    $('#ui').empty()\n    return $('<div></div>')\n        .css(\n            position: 'absolute',\n            width: 300,\n            left: '50%',\n            top: 50,\n            marginLeft: -100\n        )\n        .append($('<h1></h1>').text(title))\n        .appendTo('#ui')\n\ndisableSelect = ->\n    $('*').each ->\n        $(@)\n            .attr('unselectable', 'on')\n            .css\n               '-moz-user-select':'none',\n               '-webkit-user-select':'none',\n               'user-select':'none',\n               '-ms-user-select':'none'\n        @onselectstart = -> false\n\n    document.oncontextmenu = ->\n        return false\n\nenableSelect = ->\n    $('*').each ->\n        $(@)\n            .removeAttr('unselectable')\n            .css\n               '-moz-user-select':'text',\n               '-webkit-user-select':'text',\n               'user-select':'text',\n               '-ms-user-select':'text'\n        @onselectstart = undefined\n\n    document.oncontextmenu = undefined\n\nexports.main = ->\n    disableSelect()\n    window.canvas = $ 'canvas'\n    window.onerror = (error) ->\n        if error.search(Shader.error) > 0\n            return true\n\n    try\n        window.gl = canvas[0].getContext 'experimental-webgl'\n        if not window.gl\n            window.gl = canvas[0].getContext 'webgl'\n\n    if window.gl\n        window.quad = new Quad window.gl\n\n        stddev = gl.getExtension 'OES_standard_derivatives'\n        if not stddev\n            return errorContainer('Missing Extension: Standard Derivatives')\n                .append('''\n                    <p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/\">Standard Derivatives extension</a> which you do not have, sorry.</p>\n                ''')\n\n        floatExt = gl.getFloatExtension require: ['renderable'], prefer:['filterable', 'half'], throws:false\n        if not floatExt\n            return errorContainer('Missing Extension: Floating Point Textures')\n                .append('''\n                    <p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_texture_float/\">Floating Point Textures extension</a> which you do not have, sorry.</p>\n                ''')\n\n        Application = require('application').Application\n        application = null\n\n        loading.show 'Loading ...'\n\n        loader.hooks(load_hooks).mount\n            url: 'assets.pack',\n            loaded: (files, fs) ->\n                for name, value of files\n                    if name.match('\\.shaderlib$')\n                        fs[name] = Shader.splitLines name, value\n                try\n                    for name, value of files\n                        if name.match('\\.shader$')\n                            fs[name] = new Shader gl, name, value\n                    application = new Application(window.canvas, window.gl)\n                catch error\n                    if error == 'ShaderError'\n                        enableSelect()\n                        container = errorContainer('Shader Error').append('''\n                            <p>\n                                An error occured when compiling a shader, you can <a href=\"mailto:pyalot@gmail.com\">paste me the error</a>.\n                            </p>\n                        ''')\n                        container.css\n                            width: 600\n                            marginLeft: -300\n\n                        $('<pre></pre>')\n                            .text(Shader.lastError)\n                            .css('overflow', 'auto')\n                            .appendTo(container)\n                    else\n                        throw error\n                    \n            progress: loading.progress\n    else\n        container = errorContainer('You dont have WebGL')\n        if $.browser.msie\n            container.append('''\n                <p>\n                    You have Internet Explorer, please install\n                    <a href=\"https://www.google.com/intl/en/chrome/browser/\">Google Chrome</a> or\n                    <a href=\"http://www.mozilla.org/en-US/firefox/new/\">Firefox</a>\n                </p>\n            ''')\n        else if $.browser.webkit\n            container.append('''\n                <p>\n                    If you use OSX Safari, please <a href=\"http://www.ikriz.nl/2011/08/23/enable-webgl-in-safari\">enable WebGL manually</a>.\n                    If you use iOS Safari, you cannot use WebGL.\n                    If you use Android, please try <a href=\"http://www.mozilla.org/en-US/mobile/\">Firefox Mobile</a> or\n                    <a href=\"https://play.google.com/store/apps/details?id=com.opera.browser&hl=en\">Opera Mobile</a>\n                </p>\n            ''')\n\n        container.append('''\n            <p>\n                Please consult the <a href=\"http://support.google.com/chrome/bin/answer.py?hl=en&answer=1220892\">support pages</a>\n                on how to get WebGL for your machine.\n            </p>\n        ''')\n"
  },
  {
    "path": "src/main.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Quad, Shader, audio, disableSelect, enableSelect, errorContainer, load_hooks, loading;\n\naudio = require('audio');\n\nloading = require('loading');\n\nShader = require('webgl/shader');\n\nQuad = require('webgl/quad');\n\nrequire('webgl-nuke-vendor-prefix');\n\nrequire('webgl-texture-float-extension-shims');\n\nload_hooks = {\n  '\\.jpg$|\\.jpeg$|\\.gif$|\\.png': function(name, buffer, callback) {\n    var ext, image, mime;\n    ext = name.split('.').pop();\n    switch (ext) {\n      case 'png':\n        mime = 'image/png';\n        break;\n      case 'gif':\n        mime = 'image/gif';\n        break;\n      case 'jpg':\n      case 'jpeg':\n        mime = 'image/jpeg';\n    }\n    image = new Image();\n    image.src = getURL(buffer, mime);\n    return image.onload = function() {\n      return callback(image);\n    };\n  },\n  '\\.mpg$|\\.ogg$|\\.wav$': function(name, buffer, callback) {\n    return audio.decode(buffer, function(result) {\n      return callback(result);\n    });\n  }\n};\n\nerrorContainer = function(title) {\n  canvas.remove();\n  $('#ui').empty();\n  return $('<div></div>').css({\n    position: 'absolute',\n    width: 300,\n    left: '50%',\n    top: 50,\n    marginLeft: -100\n  }).append($('<h1></h1>').text(title)).appendTo('#ui');\n};\n\ndisableSelect = function() {\n  $('*').each(function() {\n    $(this).attr('unselectable', 'on').css({\n      '-moz-user-select': 'none',\n      '-webkit-user-select': 'none',\n      'user-select': 'none',\n      '-ms-user-select': 'none'\n    });\n    return this.onselectstart = function() {\n      return false;\n    };\n  });\n  return document.oncontextmenu = function() {\n    return false;\n  };\n};\n\nenableSelect = function() {\n  $('*').each(function() {\n    $(this).removeAttr('unselectable').css({\n      '-moz-user-select': 'text',\n      '-webkit-user-select': 'text',\n      'user-select': 'text',\n      '-ms-user-select': 'text'\n    });\n    return this.onselectstart = void 0;\n  });\n  return document.oncontextmenu = void 0;\n};\n\nexports.main = function() {\n  var Application, application, container, floatExt, stddev;\n  disableSelect();\n  window.canvas = $('canvas');\n  window.onerror = function(error) {\n    if (error.search(Shader.error) > 0) {\n      return true;\n    }\n  };\n  try {\n    window.gl = canvas[0].getContext('experimental-webgl');\n    if (!window.gl) {\n      window.gl = canvas[0].getContext('webgl');\n    }\n  } catch (_error) {}\n  if (window.gl) {\n    window.quad = new Quad(window.gl);\n    stddev = gl.getExtension('OES_standard_derivatives');\n    if (!stddev) {\n      return errorContainer('Missing Extension: Standard Derivatives').append('<p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/\">Standard Derivatives extension</a> which you do not have, sorry.</p>');\n    }\n    floatExt = gl.getFloatExtension({\n      require: ['renderable'],\n      prefer: ['filterable', 'half'],\n      throws: false\n    });\n    if (!floatExt) {\n      return errorContainer('Missing Extension: Floating Point Textures').append('<p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_texture_float/\">Floating Point Textures extension</a> which you do not have, sorry.</p>');\n    }\n    Application = require('application').Application;\n    application = null;\n    loading.show('Loading ...');\n    return loader.hooks(load_hooks).mount({\n      url: 'assets.pack',\n      loaded: function(files, fs) {\n        var container, name, value;\n        for (name in files) {\n          value = files[name];\n          if (name.match('\\.shaderlib$')) {\n            fs[name] = Shader.splitLines(name, value);\n          }\n        }\n        try {\n          for (name in files) {\n            value = files[name];\n            if (name.match('\\.shader$')) {\n              fs[name] = new Shader(gl, name, value);\n            }\n          }\n          return application = new Application(window.canvas, window.gl);\n        } catch (error) {\n          if (error === 'ShaderError') {\n            enableSelect();\n            container = errorContainer('Shader Error').append('<p>\\n    An error occured when compiling a shader, you can <a href=\"mailto:pyalot@gmail.com\">paste me the error</a>.\\n</p>');\n            container.css({\n              width: 600,\n              marginLeft: -300\n            });\n            return $('<pre></pre>').text(Shader.lastError).css('overflow', 'auto').appendTo(container);\n          } else {\n            throw error;\n          }\n        }\n      },\n      progress: loading.progress\n    });\n  } else {\n    container = errorContainer('You dont have WebGL');\n    if ($.browser.msie) {\n      container.append('<p>\\n    You have Internet Explorer, please install\\n    <a href=\"https://www.google.com/intl/en/chrome/browser/\">Google Chrome</a> or\\n    <a href=\"http://www.mozilla.org/en-US/firefox/new/\">Firefox</a>\\n</p>');\n    } else if ($.browser.webkit) {\n      container.append('<p>\\n    If you use OSX Safari, please <a href=\"http://www.ikriz.nl/2011/08/23/enable-webgl-in-safari\">enable WebGL manually</a>.\\n    If you use iOS Safari, you cannot use WebGL.\\n    If you use Android, please try <a href=\"http://www.mozilla.org/en-US/mobile/\">Firefox Mobile</a> or\\n    <a href=\"https://play.google.com/store/apps/details?id=com.opera.browser&hl=en\">Opera Mobile</a>\\n</p>');\n    }\n    return container.append('<p>\\n    Please consult the <a href=\"http://support.google.com/chrome/bin/answer.py?hl=en&answer=1220892\">support pages</a>\\n    on how to get WebGL for your machine.\\n</p>');\n  }\n};\n"
  },
  {
    "path": "src/model/materials.json",
    "content": "[{\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"00_skap.jpg\", \"diffuse_color\": {\"r\": 0.713726, \"b\": 0.658824, \"g\": 0.705882}, \"start\": 0, \"bumpmap\": \"00_skap.jpg\", \"size\": 2304}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 19.999998, \"diffuse_texture\": \"vrata_ko.jpg\", \"diffuse_color\": {\"r\": 0.784314, \"b\": 0.784314, \"g\": 0.784314}, \"start\": 2304, \"bumpmap\": \"vrata_ko.jpg\", \"size\": 726}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_st_kp.jpg\", \"diffuse_color\": {\"r\": 0.745098, \"b\": 0.67451, \"g\": 0.709804}, \"start\": 3030, \"bumpmap\": \"01_st_kp-bump.jpg\", \"size\": 16560}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"kamen.jpg\", \"diffuse_color\": {\"r\": 0.627451, \"b\": 0.560784, \"g\": 0.572549}, \"start\": 19590, \"bumpmap\": \"kamen-bump.jpg\", \"size\": 144}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"reljef.jpg\", \"diffuse_color\": {\"r\": 0.529412, \"b\": 0.490196, \"g\": 0.498039}, \"start\": 19734, \"bumpmap\": \"reljef-bump.jpg\", \"size\": 48}, {\"specular_color\": {\"r\": 0.034039, \"b\": 0.029333, \"g\": 0.032314}, \"specularity\": 1.0, \"diffuse_texture\": \"kamen-stup.jpg\", \"diffuse_color\": {\"r\": 0.941177, \"b\": 0.737255, \"g\": 0.866667}, \"start\": 19782, \"bumpmap\": \"kamen-stup.jpg\", \"size\": 33822}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"00_skap.jpg\", \"diffuse_color\": {\"r\": 0.713726, \"b\": 0.658824, \"g\": 0.705882}, \"start\": 53604, \"bumpmap\": \"00_skap.jpg\", \"size\": 17748}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"kamen.jpg\", \"diffuse_color\": {\"r\": 0.627451, \"b\": 0.560784, \"g\": 0.572549}, \"start\": 71352, \"bumpmap\": \"kamen-bump.jpg\", \"size\": 7503}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_stub.jpg\", \"diffuse_color\": {\"r\": 0.737255, \"b\": 0.670588, \"g\": 0.709804}, \"start\": 78855, \"bumpmap\": \"01_stub-bump.jpg\", \"size\": 192}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_s_ba.jpg\", \"diffuse_color\": {\"r\": 0.8, \"b\": 0.74902, \"g\": 0.784314}, \"start\": 79047, \"bumpmap\": \"01_s_ba.jpg\", \"size\": 2736}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"kamen.jpg\", \"diffuse_color\": {\"r\": 0.627451, \"b\": 0.560784, \"g\": 0.572549}, \"start\": 81783, \"bumpmap\": \"kamen-bump.png\", \"size\": 210}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 19.999998, \"diffuse_texture\": \"white.png\", \"diffuse_color\": {\"r\": 0.784314, \"b\": 0.784314, \"g\": 0.784314}, \"start\": 81993, \"bumpmap\": \"level.png\", \"size\": 1440}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_stub.jpg\", \"diffuse_color\": {\"r\": 0.737255, \"b\": 0.670588, \"g\": 0.709804}, \"start\": 83433, \"bumpmap\": \"01_stub-bump.jpg\", \"size\": 144}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_s_ba.jpg\", \"diffuse_color\": {\"r\": 0.8, \"b\": 0.74902, \"g\": 0.784314}, \"start\": 83577, \"bumpmap\": \"01_s_ba.jpg\", \"size\": 14931}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"prozor1.jpg\", \"diffuse_color\": {\"r\": 1.0, \"b\": 1.0, \"g\": 1.0}, \"start\": 98508, \"bumpmap\": \"prozor1.jpg\", \"size\": 882}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 19.999998, \"diffuse_texture\": \"vrata_kr.jpg\", \"diffuse_color\": {\"r\": 0.784314, \"b\": 0.784314, \"g\": 0.784314}, \"start\": 99390, \"bumpmap\": \"vrata_kr.jpg\", \"size\": 4878}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"01_stub.jpg\", \"diffuse_color\": {\"r\": 0.737255, \"b\": 0.670588, \"g\": 0.709804}, \"start\": 104268, \"bumpmap\": \"01_stub-bump.jpg\", \"size\": 696}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"x01_st.jpg\", \"diffuse_color\": {\"r\": 0.827451, \"b\": 0.768628, \"g\": 0.8}, \"start\": 104964, \"bumpmap\": \"level.png\", \"size\": 6756}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"sp_luk.jpg\", \"diffuse_color\": {\"r\": 0.745098, \"b\": 0.67451, \"g\": 0.709804}, \"start\": 111720, \"bumpmap\": \"sp_luk-bump.jpg\", \"size\": 25056}, {\"specular_color\": {\"r\": 0.0, \"b\": 0.0, \"g\": 0.0}, \"specularity\": 50.0, \"diffuse_texture\": \"sp_luk.jpg\", \"diffuse_color\": {\"r\": 0.745098, \"b\": 0.67451, \"g\": 0.709804}, \"start\": 136776, \"bumpmap\": \"sp_luk-bump.jpg\", \"size\": 62574}]\n"
  },
  {
    "path": "src/model/module.coffee",
    "content": "{Texture2D} = require '/webgl/texture'\n\nMaterials = class Materials\n    createTexture: (path) ->\n        texture = @texture_cache[path]\n        if not texture\n            image = get path\n            texture = new Texture2D(@gl)\n                .bind()\n                .upload(image)\n                .mipmap()\n                .repeat()\n                .unbind()\n            @texture_cache[path] = texture\n        return texture\n\n    constructor: (@gl) ->\n        @texture_cache = {}\n\n        @definitions = get 'materials.json'\n        @gl.pixelStorei @gl.UNPACK_FLIP_Y_WEBGL, true\n\n\n        for definition in @definitions\n            diffuse = \"diffuse/#{definition.diffuse_texture}\"\n            jpgbump = \"bump/#{definition.bumpmap}\"\n            pngbump = jpgbump.replace('.jpg', '.png')\n\n            definition.diffuse_texture = @createTexture diffuse\n\n            specular = definition.specular_color\n            luma = (specular.r + specular.g + specular.b)/3\n            definition.specularity = luma*definition.specularity\n\n            if get.exists pngbump\n                definition.bumpmap = @createTexture pngbump\n            else if get.exists jpgbump\n                definition.bumpmap = @createTexture jpgbump\n            else\n                definition.bumpmap = definition.diffuse_texture\n\n        @gl.pixelStorei @gl.UNPACK_FLIP_Y_WEBGL, false\n\n        @diffuse_texture = @sortById('diffuse_texture')\n        @bumpmap = @sortById('bumpmap')\n\n    sortById: (type) ->\n        result = for definition in @definitions\n            definition\n\n        result.sort (a,b) ->\n            return a[type].id - b[type].id\n        return result\n\nexports.LowresModel = class LowresModel extends require('/webgl/drawable')\n    attribs: ['position', 'texcoord', 'normal']\n    pointers: [\n        {name: 'position', size: 3, offset: 0, stride: 8},\n        {name: 'texcoord', size: 2, offset: 3, stride: 8},\n        {name: 'normal', size: 3, offset: 5, stride: 8},\n    ]\n        \n    constructor: (@gl) ->\n        super()\n        @vertices = new Float32Array(get('lowres.vertices'))\n        @size = @vertices.length/8\n        @upload @vertices\n   \nexports.Model = class Model extends require('/webgl/drawable')\n    attribs: ['position', 'texcoord', 'normal']\n    pointers: [\n        {name: 'position', size: 3, offset: 0, stride: 8},\n        {name: 'texcoord', size: 2, offset: 3, stride: 8},\n        {name: 'normal', size: 3, offset: 5, stride: 8},\n    ]\n    constructor: (@gl) ->\n        super()\n        @materials = new Materials @gl\n\n        indices = new Uint16Array(get('sponza.indices'))\n        vertices = new Float32Array(get('sponza.vertices'))\n        @size = indices.length\n        @max_angle = Math.cos(Math.PI*2*(43/360))\n        @computeVertexFaces(indices, vertices)\n        @computeFaceNormals(indices, vertices)\n        buffer = @calculateVertices(indices, vertices)\n        @upload buffer\n\n    computeVertexFaces: (indices, vertices) ->\n        start = gettime()\n\n        vertex_count = vertices.length/5\n\n        #how much storage do I need?\n        counts = new Uint8Array(vertex_count)\n        for index in indices\n            counts[index] += 1\n\n        max = 0\n        for count in counts\n            if count > max\n                max = count\n\n        @max_count = max\n\n        #store face indices\n        vertex_faces = new Uint32Array(max*vertex_count)\n        counts = new Uint8Array(vertex_count)\n        face_count = indices.length/3\n        for face_index in [0...face_count]\n            iv = face_index*3\n            idx1 = indices[iv]\n            idx2 = indices[iv+1]\n            idx3 = indices[iv+2]\n\n            c1 = counts[idx1]++\n            c2 = counts[idx2]++\n            c3 = counts[idx3]++\n\n            vertex_faces[idx1*max+c1] = face_index\n            vertex_faces[idx2*max+c2] = face_index\n            vertex_faces[idx3*max+c3] = face_index\n\n        end = gettime()\n        #console.log 'compute vertex faces', (end-start)*1000\n        @vertex_face_count = counts\n        @vertex_faces = vertex_faces\n\n    computeFaceNormals: (indices, vertices) ->\n        start = gettime()\n        face_count = indices.length/3\n        normals = new Float32Array(face_count*3)\n        \n        for i in [0...face_count]\n            iv = i*3\n            i1 = indices[iv]\n            i2 = indices[iv+1]\n            i3 = indices[iv+2]\n\n            x1 = vertices[i1*5]\n            y1 = vertices[i1*5+1]\n            z1 = vertices[i1*5+2]\n            \n            x2 = vertices[i2*5]\n            y2 = vertices[i2*5+1]\n            z2 = vertices[i2*5+2]\n            \n            x3 = vertices[i3*5]\n            y3 = vertices[i3*5+1]\n            z3 = vertices[i3*5+2]\n\n            tx=x2-x1; ty=y2-y1; tz=z2-z1\n            btx=x3-x1; bty=y3-y1; btz=z3-z1\n\n            nx = ty*btz - tz*bty\n            ny = tz*btx - tx*btz\n            nz = tx*bty - ty*btx\n            l = Math.sqrt(nx*nx + ny*ny + nz*nz)\n            nx/=l; ny/=l; nz/=l\n\n            normals[iv+0] = nx\n            normals[iv+1] = ny\n            normals[iv+2] = nz\n\n        @normals = normals\n        end = gettime()\n        #console.log 'compute face normals', (end-start)*1000\n\n    getNormal: (face_index, vertex_index) ->\n        rx = @normals[face_index*3+0]\n        ry = @normals[face_index*3+1]\n        rz = @normals[face_index*3+2]\n        #return [rx, ry, rz]\n\n        nx = 0; ny=0; nz=0\n        for c in [0...@vertex_face_count[vertex_index]]\n            vfidx = @vertex_faces[vertex_index*@max_count+c]\n            x = @normals[vfidx*3+0]\n            y = @normals[vfidx*3+1]\n            z = @normals[vfidx*3+2]\n            cos = rx*x + ry*y + rz*z\n            if cos > @max_angle\n                nx = x\n                ny = y\n                nz = z\n\n        l = Math.sqrt(nx*nx + ny*ny + nz*nz)\n        return [nx/l, ny/l, nz/l]\n\n    calculateVertices: (indices, vertices, normals) ->\n        start = gettime()\n        result = new Float32Array(indices.length*8)\n        for i in [0...indices.length/3]\n            iv = i*3\n            i1 = indices[iv]\n            i2 = indices[iv+1]\n            i3 = indices[iv+2]\n\n            x1 = vertices[i1*5]\n            y1 = vertices[i1*5+1]\n            z1 = vertices[i1*5+2]\n            u1 = vertices[i1*5+3]\n            v1 = vertices[i1*5+4]\n            \n            x2 = vertices[i2*5]\n            y2 = vertices[i2*5+1]\n            z2 = vertices[i2*5+2]\n            u2 = vertices[i2*5+3]\n            v2 = vertices[i2*5+4]\n            \n            x3 = vertices[i3*5]\n            y3 = vertices[i3*5+1]\n            z3 = vertices[i3*5+2]\n            u3 = vertices[i3*5+3]\n            v3 = vertices[i3*5+4]\n\n            [nx,ny,nz] = @getNormal i, i1\n            result[(iv+0)*8 + 0] = x1\n            result[(iv+0)*8 + 1] = y1\n            result[(iv+0)*8 + 2] = z1\n            result[(iv+0)*8 + 3] = u1\n            result[(iv+0)*8 + 4] = v1\n            result[(iv+0)*8 + 5] = nx\n            result[(iv+0)*8 + 6] = ny\n            result[(iv+0)*8 + 7] = nz\n            \n            [nx,ny,nz] = @getNormal i, i2\n            result[(iv+1)*8 + 0] = x2\n            result[(iv+1)*8 + 1] = y2\n            result[(iv+1)*8 + 2] = z2\n            result[(iv+1)*8 + 3] = u2\n            result[(iv+1)*8 + 4] = v2\n            result[(iv+1)*8 + 5] = nx\n            result[(iv+1)*8 + 6] = ny\n            result[(iv+1)*8 + 7] = nz\n            \n            [nx,ny,nz] = @getNormal i, i3\n            result[(iv+2)*8 + 0] = x3\n            result[(iv+2)*8 + 1] = y3\n            result[(iv+2)*8 + 2] = z3\n            result[(iv+2)*8 + 3] = u3\n            result[(iv+2)*8 + 4] = v3\n            result[(iv+2)*8 + 5] = nx\n            result[(iv+2)*8 + 6] = ny\n            result[(iv+2)*8 + 7] = nz\n\n        end = gettime()\n        #console.log 'build vertices', (end - start)*1000\n        return result\n\n    '''\n    draw: (shader) ->\n        if shader then @setPointersForShader shader\n        for material in @materials\n            #@gl.drawArrays @mode, @first, @size\n            @gl.drawArrays @mode, material.start, material.size\n        if shader then @disableAttribs shader\n        return @\n    '''\n"
  },
  {
    "path": "src/model/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar LowresModel, Materials, Model, Texture2D,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nTexture2D = require('/webgl/texture').Texture2D;\n\nMaterials = Materials = (function() {\n\n  Materials.prototype.createTexture = function(path) {\n    var image, texture;\n    texture = this.texture_cache[path];\n    if (!texture) {\n      image = get(path);\n      texture = new Texture2D(this.gl).bind().upload(image).mipmap().repeat().unbind();\n      this.texture_cache[path] = texture;\n    }\n    return texture;\n  };\n\n  function Materials(gl) {\n    var definition, diffuse, jpgbump, luma, pngbump, specular, _i, _len, _ref;\n    this.gl = gl;\n    this.texture_cache = {};\n    this.definitions = get('materials.json');\n    this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n    _ref = this.definitions;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      definition = _ref[_i];\n      diffuse = \"diffuse/\" + definition.diffuse_texture;\n      jpgbump = \"bump/\" + definition.bumpmap;\n      pngbump = jpgbump.replace('.jpg', '.png');\n      definition.diffuse_texture = this.createTexture(diffuse);\n      specular = definition.specular_color;\n      luma = (specular.r + specular.g + specular.b) / 3;\n      definition.specularity = luma * definition.specularity;\n      if (get.exists(pngbump)) {\n        definition.bumpmap = this.createTexture(pngbump);\n      } else if (get.exists(jpgbump)) {\n        definition.bumpmap = this.createTexture(jpgbump);\n      } else {\n        definition.bumpmap = definition.diffuse_texture;\n      }\n    }\n    this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n    this.diffuse_texture = this.sortById('diffuse_texture');\n    this.bumpmap = this.sortById('bumpmap');\n  }\n\n  Materials.prototype.sortById = function(type) {\n    var definition, result;\n    result = (function() {\n      var _i, _len, _ref, _results;\n      _ref = this.definitions;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        definition = _ref[_i];\n        _results.push(definition);\n      }\n      return _results;\n    }).call(this);\n    result.sort(function(a, b) {\n      return a[type].id - b[type].id;\n    });\n    return result;\n  };\n\n  return Materials;\n\n})();\n\nexports.LowresModel = LowresModel = (function(_super) {\n\n  __extends(LowresModel, _super);\n\n  LowresModel.prototype.attribs = ['position', 'texcoord', 'normal'];\n\n  LowresModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 8\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 8\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 8\n    }\n  ];\n\n  function LowresModel(gl) {\n    this.gl = gl;\n    LowresModel.__super__.constructor.call(this);\n    this.vertices = new Float32Array(get('lowres.vertices'));\n    this.size = this.vertices.length / 8;\n    this.upload(this.vertices);\n  }\n\n  return LowresModel;\n\n})(require('/webgl/drawable'));\n\nexports.Model = Model = (function(_super) {\n\n  __extends(Model, _super);\n\n  Model.prototype.attribs = ['position', 'texcoord', 'normal'];\n\n  Model.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 8\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 8\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 8\n    }\n  ];\n\n  function Model(gl) {\n    var buffer, indices, vertices;\n    this.gl = gl;\n    Model.__super__.constructor.call(this);\n    this.materials = new Materials(this.gl);\n    indices = new Uint16Array(get('sponza.indices'));\n    vertices = new Float32Array(get('sponza.vertices'));\n    this.size = indices.length;\n    this.max_angle = Math.cos(Math.PI * 2 * (43 / 360));\n    this.computeVertexFaces(indices, vertices);\n    this.computeFaceNormals(indices, vertices);\n    buffer = this.calculateVertices(indices, vertices);\n    this.upload(buffer);\n  }\n\n  Model.prototype.computeVertexFaces = function(indices, vertices) {\n    var c1, c2, c3, count, counts, end, face_count, face_index, idx1, idx2, idx3, index, iv, max, start, vertex_count, vertex_faces, _i, _j, _k, _len, _len1;\n    start = gettime();\n    vertex_count = vertices.length / 5;\n    counts = new Uint8Array(vertex_count);\n    for (_i = 0, _len = indices.length; _i < _len; _i++) {\n      index = indices[_i];\n      counts[index] += 1;\n    }\n    max = 0;\n    for (_j = 0, _len1 = counts.length; _j < _len1; _j++) {\n      count = counts[_j];\n      if (count > max) {\n        max = count;\n      }\n    }\n    this.max_count = max;\n    vertex_faces = new Uint32Array(max * vertex_count);\n    counts = new Uint8Array(vertex_count);\n    face_count = indices.length / 3;\n    for (face_index = _k = 0; 0 <= face_count ? _k < face_count : _k > face_count; face_index = 0 <= face_count ? ++_k : --_k) {\n      iv = face_index * 3;\n      idx1 = indices[iv];\n      idx2 = indices[iv + 1];\n      idx3 = indices[iv + 2];\n      c1 = counts[idx1]++;\n      c2 = counts[idx2]++;\n      c3 = counts[idx3]++;\n      vertex_faces[idx1 * max + c1] = face_index;\n      vertex_faces[idx2 * max + c2] = face_index;\n      vertex_faces[idx3 * max + c3] = face_index;\n    }\n    end = gettime();\n    this.vertex_face_count = counts;\n    return this.vertex_faces = vertex_faces;\n  };\n\n  Model.prototype.computeFaceNormals = function(indices, vertices) {\n    var btx, bty, btz, end, face_count, i, i1, i2, i3, iv, l, normals, nx, ny, nz, start, tx, ty, tz, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i;\n    start = gettime();\n    face_count = indices.length / 3;\n    normals = new Float32Array(face_count * 3);\n    for (i = _i = 0; 0 <= face_count ? _i < face_count : _i > face_count; i = 0 <= face_count ? ++_i : --_i) {\n      iv = i * 3;\n      i1 = indices[iv];\n      i2 = indices[iv + 1];\n      i3 = indices[iv + 2];\n      x1 = vertices[i1 * 5];\n      y1 = vertices[i1 * 5 + 1];\n      z1 = vertices[i1 * 5 + 2];\n      x2 = vertices[i2 * 5];\n      y2 = vertices[i2 * 5 + 1];\n      z2 = vertices[i2 * 5 + 2];\n      x3 = vertices[i3 * 5];\n      y3 = vertices[i3 * 5 + 1];\n      z3 = vertices[i3 * 5 + 2];\n      tx = x2 - x1;\n      ty = y2 - y1;\n      tz = z2 - z1;\n      btx = x3 - x1;\n      bty = y3 - y1;\n      btz = z3 - z1;\n      nx = ty * btz - tz * bty;\n      ny = tz * btx - tx * btz;\n      nz = tx * bty - ty * btx;\n      l = Math.sqrt(nx * nx + ny * ny + nz * nz);\n      nx /= l;\n      ny /= l;\n      nz /= l;\n      normals[iv + 0] = nx;\n      normals[iv + 1] = ny;\n      normals[iv + 2] = nz;\n    }\n    this.normals = normals;\n    return end = gettime();\n  };\n\n  Model.prototype.getNormal = function(face_index, vertex_index) {\n    var c, cos, l, nx, ny, nz, rx, ry, rz, vfidx, x, y, z, _i, _ref;\n    rx = this.normals[face_index * 3 + 0];\n    ry = this.normals[face_index * 3 + 1];\n    rz = this.normals[face_index * 3 + 2];\n    nx = 0;\n    ny = 0;\n    nz = 0;\n    for (c = _i = 0, _ref = this.vertex_face_count[vertex_index]; 0 <= _ref ? _i < _ref : _i > _ref; c = 0 <= _ref ? ++_i : --_i) {\n      vfidx = this.vertex_faces[vertex_index * this.max_count + c];\n      x = this.normals[vfidx * 3 + 0];\n      y = this.normals[vfidx * 3 + 1];\n      z = this.normals[vfidx * 3 + 2];\n      cos = rx * x + ry * y + rz * z;\n      if (cos > this.max_angle) {\n        nx = x;\n        ny = y;\n        nz = z;\n      }\n    }\n    l = Math.sqrt(nx * nx + ny * ny + nz * nz);\n    return [nx / l, ny / l, nz / l];\n  };\n\n  Model.prototype.calculateVertices = function(indices, vertices, normals) {\n    var end, i, i1, i2, i3, iv, nx, ny, nz, result, start, u1, u2, u3, v1, v2, v3, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i, _ref, _ref1, _ref2, _ref3;\n    start = gettime();\n    result = new Float32Array(indices.length * 8);\n    for (i = _i = 0, _ref = indices.length / 3; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n      iv = i * 3;\n      i1 = indices[iv];\n      i2 = indices[iv + 1];\n      i3 = indices[iv + 2];\n      x1 = vertices[i1 * 5];\n      y1 = vertices[i1 * 5 + 1];\n      z1 = vertices[i1 * 5 + 2];\n      u1 = vertices[i1 * 5 + 3];\n      v1 = vertices[i1 * 5 + 4];\n      x2 = vertices[i2 * 5];\n      y2 = vertices[i2 * 5 + 1];\n      z2 = vertices[i2 * 5 + 2];\n      u2 = vertices[i2 * 5 + 3];\n      v2 = vertices[i2 * 5 + 4];\n      x3 = vertices[i3 * 5];\n      y3 = vertices[i3 * 5 + 1];\n      z3 = vertices[i3 * 5 + 2];\n      u3 = vertices[i3 * 5 + 3];\n      v3 = vertices[i3 * 5 + 4];\n      _ref1 = this.getNormal(i, i1), nx = _ref1[0], ny = _ref1[1], nz = _ref1[2];\n      result[(iv + 0) * 8 + 0] = x1;\n      result[(iv + 0) * 8 + 1] = y1;\n      result[(iv + 0) * 8 + 2] = z1;\n      result[(iv + 0) * 8 + 3] = u1;\n      result[(iv + 0) * 8 + 4] = v1;\n      result[(iv + 0) * 8 + 5] = nx;\n      result[(iv + 0) * 8 + 6] = ny;\n      result[(iv + 0) * 8 + 7] = nz;\n      _ref2 = this.getNormal(i, i2), nx = _ref2[0], ny = _ref2[1], nz = _ref2[2];\n      result[(iv + 1) * 8 + 0] = x2;\n      result[(iv + 1) * 8 + 1] = y2;\n      result[(iv + 1) * 8 + 2] = z2;\n      result[(iv + 1) * 8 + 3] = u2;\n      result[(iv + 1) * 8 + 4] = v2;\n      result[(iv + 1) * 8 + 5] = nx;\n      result[(iv + 1) * 8 + 6] = ny;\n      result[(iv + 1) * 8 + 7] = nz;\n      _ref3 = this.getNormal(i, i3), nx = _ref3[0], ny = _ref3[1], nz = _ref3[2];\n      result[(iv + 2) * 8 + 0] = x3;\n      result[(iv + 2) * 8 + 1] = y3;\n      result[(iv + 2) * 8 + 2] = z3;\n      result[(iv + 2) * 8 + 3] = u3;\n      result[(iv + 2) * 8 + 4] = v3;\n      result[(iv + 2) * 8 + 5] = nx;\n      result[(iv + 2) * 8 + 6] = ny;\n      result[(iv + 2) * 8 + 7] = nz;\n    }\n    end = gettime();\n    return result;\n  };\n\n  'draw: (shader) ->\\n    if shader then @setPointersForShader shader\\n    for material in @materials\\n        #@gl.drawArrays @mode, @first, @size\\n        @gl.drawArrays @mode, material.start, material.size\\n    if shader then @disableAttribs shader\\n    return @';\n\n\n  return Model;\n\n})(require('/webgl/drawable'));\n"
  },
  {
    "path": "src/normaldepth.shader",
    "content": "varying vec2 vTexcoord;\nvarying vec3 vPosition, vViewPosition, vNormal, vViewNormal;\nuniform mat4 proj, view;\nuniform mat3 view_rot;\n\nvertex:\n    attribute vec3 position, normal;\n    attribute vec2 texcoord;\n\n    void main(){\n        vTexcoord = texcoord;\n        vPosition = position;\n        vNormal = normal;\n        vViewNormal = view_rot * normal;\n        vViewPosition = (view * vec4(position, 1.0)).xyz;\n\n        gl_Position = proj * view * vec4(position, 1.0);\n    }\n\nfragment:\n    #extension GL_OES_standard_derivatives : enable\n    uniform sampler2D bumpmap;\n\n    vec3 perturbedNormal(vec3 normal, float bumpheight){\n        vec3 vSigmaS = dFdx(vPosition);\n        vec3 vSigmaT = dFdy(vPosition);\n        vec3 vR1 = cross(vSigmaT, normal);\n        vec3 vR2 = cross(normal, vSigmaS);\n        float fDet = dot(vSigmaS, vR1);\n        float dBs = dFdx(bumpheight);\n        float dBt = dFdy(bumpheight);\n        vec3 vSurfGrad = sign(fDet) * (dBs*vR1 + dBt*vR2);\n        return normalize(abs(fDet)*normal-vSurfGrad);\n    }\n\n    void main(){\n        vec3 normal = normalize(vNormal);\n        float bumpheight = texture2D(bumpmap, vTexcoord).r;\n        vec3 perturbed_normal = perturbedNormal(normal, bumpheight/96.0);\n        float depth = length(vViewPosition);\n        vec3 eye_dir = normalize(vViewPosition);\n        float displacement = dot(eye_dir, -(view_rot*normal)) * bumpheight*0.05;\n\n        gl_FragColor = vec4(perturbed_normal, depth-displacement);\n    }\n"
  },
  {
    "path": "src/presets/default.json",
    "content": "{\n  \"remembered\": {\n    \"Default\": {\n      \"0\": {\n        \"resolution_label\": \"1:2 default\",\n        \"show_fps\": false\n      },\n      \"1\": {\n        \"inputGamma\": 1.8,\n        \"outputGamma\": 1.99100719424,\n        \"brightness\": 1.51079136691,\n        \"saturation\": 1.0071942446\n      },\n      \"2\": {\n        \"orientation\": 104,\n        \"elevation\": 53.8686131387\n      },\n      \"3\": {\n        \"draw_probes\": false,\n        \"gi\": 0.762589928058,\n        \"di\": 0.172661870504,\n        \"ao\": 0.700729927007\n      },\n      \"4\": {\n        \"sunColor\": [\n          255,\n          248.823529412,\n          202.5\n        ],\n        \"sunRadiance\": 9.4964028777,\n        \"skyColor\": [\n          9.90196078431,\n          66.9838523645,\n          252.5\n        ],\n        \"skyRadiance\": 1.0071942446,\n        \"giGain\": 0.7,\n        \"bounces\": 3\n      },\n      \"5\": {\n        \"c1\": 1.15107913669,\n        \"c2\": 2.41726618705,\n        \"band3\": 0.517985611511,\n        \"c3\": 3.13669064748,\n        \"c4\": 0.546762589928,\n        \"c5\": 1.87050359712\n      },\n      \"6\": {\n        \"x\": -9.38136276391469,\n        \"y\": 3.176749303559157,\n        \"z\": 0.09001503384880467,\n        \"go\": 92.0781892939057,\n        \"p\": 0.2106932539339603\n      },\n      \"7\": {\n        \"subpixel_aa\": 0.75,\n        \"contrast_treshold\": 0.166,\n        \"edge_treshold\": 0\n      },\n      \"8\": {\n        \"show_all\": false,\n        \"window_label\": \"Antialiased\",\n        \"show_label\": false\n      }\n    }\n  },\n  \"folders\": {\n    \"Performance\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Picture\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Compositing\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Lighting\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Harmonics\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Camera\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Sun\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Antialias\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Views\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    }\n  },\n  \"preset\": \"Default\",\n  \"closed\": true\n}\n"
  },
  {
    "path": "src/presets/new.json",
    "content": "{\n  \"remembered\": {\n    \"Apple Gamma\": {\n      \"1\": {\n        \"outputGamma\": 2.5,\n        \"brightness\": 1.3218978102189782,\n        \"saturation\": 0.95071942446\n      }\n    },\n    \"Default\": {\n      \"0\": {\n        \"resolution_label\": \"1:2 default\",\n        \"show_fps\": false\n      },\n      \"1\": {\n        \"inputGamma\": 1.8,\n        \"outputGamma\": 2.1,\n        \"brightness\": 1.0218978102189782,\n        \"saturation\": 1.0071942446\n      },\n      \"2\": {\n        \"orientation\": 102.48175182481751,\n        \"elevation\": 51.240875912408754\n      },\n      \"3\": {\n        \"draw_probes\": false,\n        \"gi\": 0.9927007299270073,\n        \"di\": 0.8321167883211679,\n        \"ao\": 0.700729927007\n      },\n      \"4\": {\n        \"sunColor\": [\n          255,\n          248.823529412,\n          202.5\n        ],\n        \"sunRadiance\": 5.5,\n        \"skyColor\": [\n            0,\n            35, \n            255\n        ],\n        \"skyRadiance\": 0.8,\n        \"giGain\": 1.6058394160583942,\n        \"bounces\": 3\n      },\n      \"5\": {\n        \"c1\": 1.0359712230215827,\n        \"c2\": 1.841726618705036,\n        \"band3\": 0.8345323741007195,\n        \"c3\": 2.935251798561151,\n        \"c4\": 0.5755395683453237,\n        \"c5\": 1.064748201438849\n      },\n      \"6\": {\n        \"x\": -9.904411786477144,\n        \"y\": 1.864264505425676,\n        \"z\": -0.5129541306187764,\n        \"go\": 112.499999992655,\n        \"p\": -4.316055717198253\n      },\n      \"7\": {\n        \"subpixel_aa\": 0.75,\n        \"contrast_treshold\": 0.166,\n        \"edge_treshold\": 0\n      },\n      \"8\": {\n        \"show_all\": false,\n        \"window_label\": \"Antialiased\",\n        \"show_label\": false\n      }\n    },\n    \"Bright Day\": {\n      \"1\": {\n        \"brightness\": 1.0218978102189782\n      },\n      \"2\": {\n        \"orientation\": 102.48175182481751,\n        \"elevation\": 51.240875912408754\n      },\n      \"4\": {\n        \"sunColor\": [\n          255,\n          248.823529412,\n          202.5\n        ],\n        \"sunRadiance\": 5.5,\n        \"skyColor\": [\n            0,\n            35, \n            255\n        ],\n        \"skyRadiance\": 0.8\n      }\n    },\n    \"Morning Mood\": {\n      \"1\": {\n        \"brightness\": 1.7266187050359714\n      },\n      \"2\": {\n        \"orientation\": 102.481751825,\n        \"elevation\": 7.769784172661871\n      },\n      \"4\": {\n        \"sunColor\": [\n          252.5,\n          178.81776239907728,\n          138.62745098039215\n        ],\n        \"sunRadiance\": 2.5899280575539567,\n        \"skyColor\": [\n          74.63235294117646,\n          94.24163783160323,\n          217.5\n        ],\n        \"skyRadiance\": 0.8\n      }\n    },\n    \"Noon\": {\n      \"1\": {\n        \"brightness\": 1.0218978102189782\n      },\n      \"2\": {\n        \"orientation\": 160.57553956834533,\n        \"elevation\": 78.34532374100719\n      },\n      \"4\": {\n        \"sunColor\": [\n          255,\n          255,\n          255\n        ],\n        \"sunRadiance\": 6.9064748201438855,\n        \"skyColor\": [\n          140,\n          155.7843137254902,\n          255\n        ],\n        \"skyRadiance\": 2.5899280575539567\n      }\n    }\n  },\n  \"folders\": {\n    \"Performance\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Picture\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Compositing\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Lighting\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Harmonics\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Camera\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Sun\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    },\n    \"Antialias\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": true\n    },\n    \"Views\": {\n      \"folders\": {},\n      \"preset\": \"Default\",\n      \"closed\": false\n    }\n  },\n  \"preset\": \"Default\",\n  \"closed\": true\n}\n"
  },
  {
    "path": "src/ssao/module.coffee",
    "content": "Rendernode = require '/rendernode'\nBlur = require '/blur'\n\nreturn class SSAO\n    constructor: (gl, @normaldepth) ->\n        floatExt = gl.getFloatExtension require: ['renderable', 'filterable']\n\n        @moments = new Rendernode gl,\n            program: get 'moments.shader'\n            type: floatExt.type\n            drawable: quad\n\n        @blur = new Blur gl, type: floatExt.type\n\n        @output = new Rendernode gl,\n            program: get 'ssao.shader'\n            drawable: quad\n\n    update: ->\n        @moments.start()\n            .sampler('normaldepth', @normaldepth)\n            .f('range', 42)\n            .clear()\n            .draw()\n            .end()\n\n        @blur.update(@moments)\n\n        @output.start()\n            .sampler('normaldepth', @normaldepth)\n            .sampler('momentsmap', @blur.output)\n            .f('range', 42)\n            .clear()\n            .draw()\n            .end()\n\n    resize: (width, height) ->\n        @moments.resize width/2, height/2\n        @blur.resize width/4, height/4\n        @output.resize width, height\n"
  },
  {
    "path": "src/ssao/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Blur, Rendernode, SSAO;\n\nRendernode = require('/rendernode');\n\nBlur = require('/blur');\n\nreturn SSAO = (function() {\n\n  function SSAO(gl, normaldepth) {\n    var floatExt;\n    this.normaldepth = normaldepth;\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.moments = new Rendernode(gl, {\n      program: get('moments.shader'),\n      type: floatExt.type,\n      drawable: quad\n    });\n    this.blur = new Blur(gl, {\n      type: floatExt.type\n    });\n    this.output = new Rendernode(gl, {\n      program: get('ssao.shader'),\n      drawable: quad\n    });\n  }\n\n  SSAO.prototype.update = function() {\n    this.moments.start().sampler('normaldepth', this.normaldepth).f('range', 42).clear().draw().end();\n    this.blur.update(this.moments);\n    return this.output.start().sampler('normaldepth', this.normaldepth).sampler('momentsmap', this.blur.output).f('range', 42).clear().draw().end();\n  };\n\n  SSAO.prototype.resize = function(width, height) {\n    this.moments.resize(width / 2, height / 2);\n    this.blur.resize(width / 4, height / 4);\n    return this.output.resize(width, height);\n  };\n\n  return SSAO;\n\n})();\n"
  },
  {
    "path": "src/ssao/moments.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D normaldepth;\n    uniform vec2 viewport;\n    uniform float range;\n        \n    void main(){\n        vec4 data = texture2D(normaldepth, gl_FragCoord.xy/viewport);\n        float depth = data.w;\n        float scaled = clamp(depth/range, 0.0, 1.0);\n        gl_FragColor = vec4(scaled, scaled*scaled, 0.0, 1.0);\n        //float dx = dFdx(scaled);\n        //float dy = dFdy(scaled);\n        //gl_FragColor = vec4(scaled, scaled*scaled + 0.25*(dx*dx + dy*dy), 0.0, 1.0);\n    }\n        \n"
  },
  {
    "path": "src/ssao/ssao.shader",
    "content": "vertex:\n    attribute vec2 position;\n\n    void main(){\n        gl_Position = vec4(position, 0.0, 1.0);\n    }\n\nfragment:\n    uniform sampler2D normaldepth, momentsmap;\n    uniform vec2 viewport;\n    uniform float range;\n\n    float linstep(float low, float high, float v){\n        return clamp((v-low)/(high-low), 0.0, 1.0);\n    }\n\n    float getOcclusion(float depth, vec2 moments, float offset){\n        float p = smoothstep(depth-offset/range, depth, moments.x);\n        //float p = step(depth-offset/range, moments.x);\n        float variance = moments.y - moments.x*moments.x;\n        float d = depth - moments.x;\n        float p_max = variance/(variance+d*d);\n        p_max = smoothstep(0.5, 1.0, p_max);\n        return 1.0-clamp(max(p, p_max), 0.0, 1.0);\n    }\n        \n    void main(){\n        float depth = clamp(texture2D(normaldepth, gl_FragCoord.xy/viewport).w/range, 0.0, 1.0);\n        vec2 moments = texture2D(momentsmap, gl_FragCoord.xy/viewport).xy;\n        float factor = smoothstep((depth-0.2/range), depth, moments.x);\n        float result = getOcclusion(depth, moments, 0.025)*clamp(factor, 0.0, 1.0);\n        gl_FragColor = vec4(1.0-pow(result, 0.5));\n    }\n"
  },
  {
    "path": "src/sun.coffee",
    "content": "return class Sun extends require('events')\n    constructor: (gui, @orientation=104, @elevation=60) ->\n        gui.remember @\n        super()\n        folder = gui.addFolder('Sun')\n        folder.add(@, 'orientation', 0, 360).onChange(@update)\n        folder.add(@, 'elevation', 0, 90).onChange(@update)\n\n        @near = -1\n        @far = 41\n        @proj = new Mat4().ortho(@near, @far, 21, -21, -21, 21)\n        @view = new Mat4()\n        @rot = new Mat3()\n        @update()\n\n    update: =>\n        @view.identity()\n            .translateVal3(0, 0, -21)\n            .rotatex(@elevation)\n            .rotatey(@orientation)\n            .translateVal3(0, -7.5, 0)\n            .toMat3 @rot.identity()\n\n        @trigger('change')\n        return @\n\n"
  },
  {
    "path": "src/sun.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Sun,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Sun = (function(_super) {\n\n  __extends(Sun, _super);\n\n  function Sun(gui, orientation, elevation) {\n    var folder;\n    this.orientation = orientation != null ? orientation : 104;\n    this.elevation = elevation != null ? elevation : 60;\n    this.update = __bind(this.update, this);\n\n    gui.remember(this);\n    Sun.__super__.constructor.call(this);\n    folder = gui.addFolder('Sun');\n    folder.add(this, 'orientation', 0, 360).onChange(this.update);\n    folder.add(this, 'elevation', 0, 90).onChange(this.update);\n    this.near = -1;\n    this.far = 41;\n    this.proj = new Mat4().ortho(this.near, this.far, 21, -21, -21, 21);\n    this.view = new Mat4();\n    this.rot = new Mat3();\n    this.update();\n  }\n\n  Sun.prototype.update = function() {\n    this.view.identity().translateVal3(0, 0, -21).rotatex(this.elevation).rotatey(this.orientation).translateVal3(0, -7.5, 0).toMat3(this.rot.identity());\n    this.trigger('change');\n    return this;\n  };\n\n  return Sun;\n\n})(require('events'));\n"
  },
  {
    "path": "src/windows/module.coffee",
    "content": "Quad = require '/webgl/quad'\nRendernode = require '/rendernode'\nkeys = require '/keys'\n\nclass Window\n    constructor: (@index, @texture, @node, @x, @y) ->\n        @label = @texture.label\n\n        if @texture.diva\n            @diva = 1\n        else\n            @diva = 0\n\n        if @texture.gamma == false\n            @gamma = 0\n        else\n            @gamma = 1\n\n        if @texture.affine\n            @mul = @texture.affine[0]\n            @add = @texture.affine[1]\n        else\n            @mul = 1\n            @add = 0\n\n    draw: (xscale, yscale, one2one, cx, cy, active) ->\n        width = @texture.tex.width\n        height = @texture.tex.height\n        max = Math.max width, height\n\n        w = width/max\n        h = height/max\n\n        s = 1/Math.max(w*xscale, h*yscale)\n        w = w * (1-one2one) + s*w*one2one\n        h = h * (1-one2one) + s*h*one2one\n\n        @node\n            .sampler('source', @texture.tex)\n            .f('mixgamma', @gamma)\n            .f('diva', @diva)\n            .f('border_factor', active)\n            .val2('affine', @mul, @add)\n            .val2('size', w*xscale, h*yscale)\n            .val2('offset', (@x-cx)*xscale, (@y-cy)*yscale)\n            .draw()\n\nreturn class Windows\n    constructor: (@gl, gui, @textures) ->\n        gui.remember @\n\n        @label = $('<div id=\"windowlabel\">test</div>').appendTo('#ui').hide()\n        @show_all = false\n        @show_label = false\n        @needs_clear = $.browser.mozilla\n        #console.log @needs_clear\n\n        @node = new Rendernode @gl,\n            front: true\n            program: get 'window.shader'\n            drawable: quad\n\n        @windows = []\n        @labelmap = {}\n        labels = []\n\n        gridsize = Math.ceil(Math.sqrt(@textures.length))\n        for texture, i in @textures\n            x = i%gridsize\n            y = gridsize - Math.floor(i/gridsize) - 1\n            window = new Window i, texture, @node, x*2.2, y*2.2\n            @labelmap[window.label] = window\n            @windows.push window\n            labels.push window.label\n\n        minx = null\n        maxx = null\n        miny = null\n        maxy = null\n\n        for window in @windows\n            minx = if minx!=null then Math.min(window.x, minx) else window.x\n            maxx = if maxx!=null then Math.max(window.x, maxx) else window.x\n            miny = if miny!=null then Math.min(window.y, miny) else window.y\n            maxy = if maxy!=null then Math.max(window.y, maxy) else window.y\n\n        @cx = (minx+maxx)/2\n        @cy = (miny+maxy)/2\n        @full_scale = 1.9/Math.min(maxx-minx+2, maxy-miny+2)\n\n        @zoom = 0.0\n\n        @active = @windows.length - 1\n        keys.press 'right', @next\n        keys.press 'left', @prev\n\n        keys.press 'down', =>\n            new_value = @active + gridsize\n            if new_value < @windows.length\n                @active = new_value\n            else\n                @active = @active % gridsize\n            @setActive()\n        \n        keys.press 'up', =>\n            new_value = @active - gridsize\n            if new_value >= 0\n                @active = new_value\n            else\n                new_value = gridsize*gridsize + new_value\n                while new_value >= @windows.length\n                    new_value -= gridsize\n                @active = new_value\n            @setActive()\n\n        keys.press 'space', =>\n            @show_all = not @show_all\n            @all_ctrl.setValue(@show_all)\n        keys.press 'enter', =>\n            @show_all = not @show_all\n            @all_ctrl.setValue(@show_all)\n\n        active = @getActive()\n        @x = active.x\n        @y = active.y\n       \n        folder = gui.addFolder('Views')\n        @all_ctrl = folder.add(@, 'show_all').name('Overview')\n        folder.add(@, 'next').name('Next view')\n        folder.add(@, 'prev').name('Prev view')\n\n        @window_label = active.label\n        @guiLabel = folder.add(@, 'window_label', labels).name('View').onChange(@guiLabelChange)\n        folder.add(@, 'show_label').name('Labels').onChange @labelVisibilityChange\n        @guiLabelChange()\n\n    labelVisibilityChange: =>\n        if @show_label\n            @label.clearQueue().fadeIn()\n        else\n            @label.clearQueue().fadeOut()\n\n\n    guiLabelChange: =>\n        window = @labelmap[@window_label]\n        @active = window.index\n        @setActive()\n\n    getActive: -> @windows[@active]\n        \n    setActive: ->\n        text = @getActive().label\n        @window_label = text\n        @guiLabel.updateDisplay()\n        @label.text(text)\n\n    next: =>\n        @active = (@active+1) % @windows.length\n        @setActive()\n    prev: =>\n        if @active == 0\n            @active = @windows.length - 1\n        else\n            @active -= 1\n        @setActive()\n\n    step: ->\n        active = @getActive()\n        tx = active.x\n        ty = active.y\n\n        @x = @x+(tx-@x)*0.1\n        @y = @y+(ty-@y)*0.1\n\n        if @show_all\n            @zoom = @zoom + (1-@zoom)*0.1\n        else\n            @zoom = @zoom + (0-@zoom)*0.1\n\n    draw: (gamma) ->\n        @step()\n        if @needs_clear == true\n            @gl.clearColor 0, 0, 0, 0\n            @gl.clear @gl.COLOR_BUFFER_BIT | @gl.DEPTH_BUFFER_BIT\n        @node\n            .start()\n            .f('gamma', gamma)\n\n        width = @node.width\n        height = @node.height\n\n        if width > height\n            xscale = height/width\n            yscale = 1\n        else\n            xscale = 1\n            yscale = width/height\n\n        factor = 1.0-@zoom + @zoom * @full_scale\n        #factor = @full_scale\n        xscale *= factor\n        yscale *= factor\n\n        active = @getActive()\n\n        for window in @windows\n            if window != active\n                @drawWindow xscale, yscale, window, 0\n\n        @drawWindow xscale, yscale, active, 1\n\n        @node.end()\n\n    drawWindow: (xscale, yscale, window, active) ->\n        dx = window.x - @x\n        dy = window.y - @y\n        l = Math.sqrt(dx*dx+dy*dy)\n        if l > 0\n            one2one = Math.min(1/(l*2), 1)\n        else\n            one2one = 1\n\n        x = @x*(1-@zoom) + @cx*@zoom\n        y = @y*(1-@zoom) + @cy*@zoom\n        active = Math.pow(one2one, 2.0) * @zoom\n\n        window.draw(xscale, yscale, one2one*(1-@zoom), x, y, active)\n        \n"
  },
  {
    "path": "src/windows/module.js",
    "content": "// Generated by CoffeeScript 1.3.3\nvar Quad, Rendernode, Window, Windows, keys,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nQuad = require('/webgl/quad');\n\nRendernode = require('/rendernode');\n\nkeys = require('/keys');\n\nWindow = (function() {\n\n  function Window(index, texture, node, x, y) {\n    this.index = index;\n    this.texture = texture;\n    this.node = node;\n    this.x = x;\n    this.y = y;\n    this.label = this.texture.label;\n    if (this.texture.diva) {\n      this.diva = 1;\n    } else {\n      this.diva = 0;\n    }\n    if (this.texture.gamma === false) {\n      this.gamma = 0;\n    } else {\n      this.gamma = 1;\n    }\n    if (this.texture.affine) {\n      this.mul = this.texture.affine[0];\n      this.add = this.texture.affine[1];\n    } else {\n      this.mul = 1;\n      this.add = 0;\n    }\n  }\n\n  Window.prototype.draw = function(xscale, yscale, one2one, cx, cy, active) {\n    var h, height, max, s, w, width;\n    width = this.texture.tex.width;\n    height = this.texture.tex.height;\n    max = Math.max(width, height);\n    w = width / max;\n    h = height / max;\n    s = 1 / Math.max(w * xscale, h * yscale);\n    w = w * (1 - one2one) + s * w * one2one;\n    h = h * (1 - one2one) + s * h * one2one;\n    return this.node.sampler('source', this.texture.tex).f('mixgamma', this.gamma).f('diva', this.diva).f('border_factor', active).val2('affine', this.mul, this.add).val2('size', w * xscale, h * yscale).val2('offset', (this.x - cx) * xscale, (this.y - cy) * yscale).draw();\n  };\n\n  return Window;\n\n})();\n\nreturn Windows = (function() {\n\n  function Windows(gl, gui, textures) {\n    var active, folder, gridsize, i, labels, maxx, maxy, minx, miny, texture, window, x, y, _i, _j, _len, _len1, _ref, _ref1,\n      _this = this;\n    this.gl = gl;\n    this.textures = textures;\n    this.prev = __bind(this.prev, this);\n\n    this.next = __bind(this.next, this);\n\n    this.guiLabelChange = __bind(this.guiLabelChange, this);\n\n    this.labelVisibilityChange = __bind(this.labelVisibilityChange, this);\n\n    gui.remember(this);\n    this.label = $('<div id=\"windowlabel\">test</div>').appendTo('#ui').hide();\n    this.show_all = false;\n    this.show_label = false;\n    this.needs_clear = $.browser.mozilla;\n    this.node = new Rendernode(this.gl, {\n      front: true,\n      program: get('window.shader'),\n      drawable: quad\n    });\n    this.windows = [];\n    this.labelmap = {};\n    labels = [];\n    gridsize = Math.ceil(Math.sqrt(this.textures.length));\n    _ref = this.textures;\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      texture = _ref[i];\n      x = i % gridsize;\n      y = gridsize - Math.floor(i / gridsize) - 1;\n      window = new Window(i, texture, this.node, x * 2.2, y * 2.2);\n      this.labelmap[window.label] = window;\n      this.windows.push(window);\n      labels.push(window.label);\n    }\n    minx = null;\n    maxx = null;\n    miny = null;\n    maxy = null;\n    _ref1 = this.windows;\n    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n      window = _ref1[_j];\n      minx = minx !== null ? Math.min(window.x, minx) : window.x;\n      maxx = maxx !== null ? Math.max(window.x, maxx) : window.x;\n      miny = miny !== null ? Math.min(window.y, miny) : window.y;\n      maxy = maxy !== null ? Math.max(window.y, maxy) : window.y;\n    }\n    this.cx = (minx + maxx) / 2;\n    this.cy = (miny + maxy) / 2;\n    this.full_scale = 1.9 / Math.min(maxx - minx + 2, maxy - miny + 2);\n    this.zoom = 0.0;\n    this.active = this.windows.length - 1;\n    keys.press('right', this.next);\n    keys.press('left', this.prev);\n    keys.press('down', function() {\n      var new_value;\n      new_value = _this.active + gridsize;\n      if (new_value < _this.windows.length) {\n        _this.active = new_value;\n      } else {\n        _this.active = _this.active % gridsize;\n      }\n      return _this.setActive();\n    });\n    keys.press('up', function() {\n      var new_value;\n      new_value = _this.active - gridsize;\n      if (new_value >= 0) {\n        _this.active = new_value;\n      } else {\n        new_value = gridsize * gridsize + new_value;\n        while (new_value >= _this.windows.length) {\n          new_value -= gridsize;\n        }\n        _this.active = new_value;\n      }\n      return _this.setActive();\n    });\n    keys.press('space', function() {\n      _this.show_all = !_this.show_all;\n      return _this.all_ctrl.setValue(_this.show_all);\n    });\n    keys.press('enter', function() {\n      _this.show_all = !_this.show_all;\n      return _this.all_ctrl.setValue(_this.show_all);\n    });\n    active = this.getActive();\n    this.x = active.x;\n    this.y = active.y;\n    folder = gui.addFolder('Views');\n    this.all_ctrl = folder.add(this, 'show_all').name('Overview');\n    folder.add(this, 'next').name('Next view');\n    folder.add(this, 'prev').name('Prev view');\n    this.window_label = active.label;\n    this.guiLabel = folder.add(this, 'window_label', labels).name('View').onChange(this.guiLabelChange);\n    folder.add(this, 'show_label').name('Labels').onChange(this.labelVisibilityChange);\n    this.guiLabelChange();\n  }\n\n  Windows.prototype.labelVisibilityChange = function() {\n    if (this.show_label) {\n      return this.label.clearQueue().fadeIn();\n    } else {\n      return this.label.clearQueue().fadeOut();\n    }\n  };\n\n  Windows.prototype.guiLabelChange = function() {\n    var window;\n    window = this.labelmap[this.window_label];\n    this.active = window.index;\n    return this.setActive();\n  };\n\n  Windows.prototype.getActive = function() {\n    return this.windows[this.active];\n  };\n\n  Windows.prototype.setActive = function() {\n    var text;\n    text = this.getActive().label;\n    this.window_label = text;\n    this.guiLabel.updateDisplay();\n    return this.label.text(text);\n  };\n\n  Windows.prototype.next = function() {\n    this.active = (this.active + 1) % this.windows.length;\n    return this.setActive();\n  };\n\n  Windows.prototype.prev = function() {\n    if (this.active === 0) {\n      this.active = this.windows.length - 1;\n    } else {\n      this.active -= 1;\n    }\n    return this.setActive();\n  };\n\n  Windows.prototype.step = function() {\n    var active, tx, ty;\n    active = this.getActive();\n    tx = active.x;\n    ty = active.y;\n    this.x = this.x + (tx - this.x) * 0.1;\n    this.y = this.y + (ty - this.y) * 0.1;\n    if (this.show_all) {\n      return this.zoom = this.zoom + (1 - this.zoom) * 0.1;\n    } else {\n      return this.zoom = this.zoom + (0 - this.zoom) * 0.1;\n    }\n  };\n\n  Windows.prototype.draw = function(gamma) {\n    var active, factor, height, width, window, xscale, yscale, _i, _len, _ref;\n    this.step();\n    if (this.needs_clear === true) {\n      this.gl.clearColor(0, 0, 0, 0);\n      this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n    }\n    this.node.start().f('gamma', gamma);\n    width = this.node.width;\n    height = this.node.height;\n    if (width > height) {\n      xscale = height / width;\n      yscale = 1;\n    } else {\n      xscale = 1;\n      yscale = width / height;\n    }\n    factor = 1.0 - this.zoom + this.zoom * this.full_scale;\n    xscale *= factor;\n    yscale *= factor;\n    active = this.getActive();\n    _ref = this.windows;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      window = _ref[_i];\n      if (window !== active) {\n        this.drawWindow(xscale, yscale, window, 0);\n      }\n    }\n    this.drawWindow(xscale, yscale, active, 1);\n    return this.node.end();\n  };\n\n  Windows.prototype.drawWindow = function(xscale, yscale, window, active) {\n    var dx, dy, l, one2one, x, y;\n    dx = window.x - this.x;\n    dy = window.y - this.y;\n    l = Math.sqrt(dx * dx + dy * dy);\n    if (l > 0) {\n      one2one = Math.min(1 / (l * 2), 1);\n    } else {\n      one2one = 1;\n    }\n    x = this.x * (1 - this.zoom) + this.cx * this.zoom;\n    y = this.y * (1 - this.zoom) + this.cy * this.zoom;\n    active = Math.pow(one2one, 2.0) * this.zoom;\n    return window.draw(xscale, yscale, one2one * (1 - this.zoom), x, y, active);\n  };\n\n  return Windows;\n\n})();\n"
  },
  {
    "path": "src/windows/window.shader",
    "content": "varying vec2 vTexcoord, vPosition;\n\nvertex:\n    attribute vec2 position;\n    uniform vec2 size;\n    uniform vec2 offset;\n\n    void main(){\n        vPosition = position;\n        vTexcoord = position * 0.5 + 0.5;\n        gl_Position = vec4(position*size+offset, 0.0, 1.0);\n    }\n\nfragment:\n    #extension GL_OES_standard_derivatives : enable\n    uniform sampler2D source;\n    uniform float diva, gamma, mixgamma, border_factor;\n    uniform vec2 affine;\n    \n    float edgeFactor(vec2 src){\n        vec2 d = fwidth(src);\n        vec2 a3 = smoothstep(vec2(0.0), d*1.5, src);\n        return min(a3.x, a3.y);\n    }\n        \n    void main(){\n        vec4 data = texture2D(source, vTexcoord);\n        vec3 transformed = data.rgb*affine.x + affine.y;\n        vec3 color;\n        if(data.a == 0.0){\n            color = transformed;\n        }\n        else{\n            color = mix(transformed, data.rgb/data.a, diva);\n        }\n        vec3 corrected = pow(color, vec3(1.0/gamma));\n        vec3 output_color = mix(color, corrected, mixgamma);\n        vec3 clamped = clamp(output_color, vec3(0.0), vec3(1.0));\n\n        vec2 dpos = fwidth(vPosition);\n        vec2 pos = smoothstep(1.0-dpos*4.0, vec2(1.0), abs(vPosition));\n        float near = border_factor * max(pos.x, pos.y);\n        gl_FragColor = vec4(mix(clamped, vec3(1.0, 0.5, 0.0), near), 1.0);\n    }\n"
  },
  {
    "path": "www/code.js",
    "content": "\nFunction.prototype.property = function(prop, desc) {\n    Object.defineProperty(this.prototype, prop, desc);\n};\n\n/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\nvar dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){var a=a||document,c=a.createElement(\"link\");c.type=\"text/css\";c.rel=\"stylesheet\";c.href=e;a.getElementsByTagName(\"head\")[0].appendChild(c)},inject:function(e,a){var a=a||document,c=document.createElement(\"style\");c.type=\"text/css\";c.innerHTML=e;a.getElementsByTagName(\"head\")[0].appendChild(c)}}}();\ndat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(c[f]=a[f])},this);return c},defaults:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(c[f])&&(c[f]=a[f])},this);return c},compose:function(){var c=a.call(arguments);return function(){for(var d=a.call(arguments),f=c.length-1;f>=0;f--)d=[c[f].apply(this,d)];return d[0]}},\neach:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b<n;b++){if(b in a&&d.call(f,a[b],b)===this.BREAK)break}else for(b in a)if(d.call(f,a[b],b)===this.BREAK)break},defer:function(a){setTimeout(a,0)},toArray:function(c){return c.toArray?c.toArray():a.call(c)},isUndefined:function(a){return a===void 0},isNull:function(a){return a===null},isNaN:function(a){return a!==a},isArray:Array.isArray||function(a){return a.constructor===Array},isObject:function(a){return a===\nObject(a)},isNumber:function(a){return a===a+0},isString:function(a){return a===a+\"\"},isBoolean:function(a){return a===false||a===true},isFunction:function(a){return Object.prototype.toString.call(a)===\"[object Function]\"}}}();\ndat.controllers.Controller=function(e){var a=function(a,d){this.initialValue=a[d];this.domElement=document.createElement(\"div\");this.object=a;this.property=d;this.__onFinishChange=this.__onChange=void 0};e.extend(a.prototype,{onChange:function(a){this.__onChange=a;return this},onFinishChange:function(a){this.__onFinishChange=a;return this},setValue:function(a){this.object[this.property]=a;this.__onChange&&this.__onChange.call(this,a);this.updateDisplay();return this},getValue:function(){return this.object[this.property]},\nupdateDisplay:function(){return this},isModified:function(){return this.initialValue!==this.getValue()}});return a}(dat.utils.common);\ndat.dom.dom=function(e){function a(b){if(b===\"0\"||e.isUndefined(b))return 0;b=b.match(d);return!e.isNull(b)?parseFloat(b[1]):0}var c={};e.each({HTMLEvents:[\"change\"],MouseEvents:[\"click\",\"mousemove\",\"mousedown\",\"mouseup\",\"mouseover\"],KeyboardEvents:[\"keydown\"]},function(b,a){e.each(b,function(b){c[b]=a})});var d=/(\\d+(\\.\\d+)?)px/,f={makeSelectable:function(b,a){if(!(b===void 0||b.style===void 0))b.onselectstart=a?function(){return false}:function(){},b.style.MozUserSelect=a?\"auto\":\"none\",b.style.KhtmlUserSelect=\na?\"auto\":\"none\",b.unselectable=a?\"on\":\"off\"},makeFullscreen:function(b,a,d){e.isUndefined(a)&&(a=true);e.isUndefined(d)&&(d=true);b.style.position=\"absolute\";if(a)b.style.left=0,b.style.right=0;if(d)b.style.top=0,b.style.bottom=0},fakeEvent:function(b,a,d,f){var d=d||{},m=c[a];if(!m)throw Error(\"Event type \"+a+\" not supported.\");var l=document.createEvent(m);switch(m){case \"MouseEvents\":l.initMouseEvent(a,d.bubbles||false,d.cancelable||true,window,d.clickCount||1,0,0,d.x||d.clientX||0,d.y||d.clientY||\n0,false,false,false,false,0,null);break;case \"KeyboardEvents\":m=l.initKeyboardEvent||l.initKeyEvent;e.defaults(d,{cancelable:true,ctrlKey:false,altKey:false,shiftKey:false,metaKey:false,keyCode:void 0,charCode:void 0});m(a,d.bubbles||false,d.cancelable,window,d.ctrlKey,d.altKey,d.shiftKey,d.metaKey,d.keyCode,d.charCode);break;default:l.initEvent(a,d.bubbles||false,d.cancelable||true)}e.defaults(l,f);b.dispatchEvent(l)},bind:function(b,a,d,c){b.addEventListener?b.addEventListener(a,d,c||false):b.attachEvent&&\nb.attachEvent(\"on\"+a,d);return f},unbind:function(b,a,d,c){b.removeEventListener?b.removeEventListener(a,d,c||false):b.detachEvent&&b.detachEvent(\"on\"+a,d);return f},addClass:function(b,a){if(b.className===void 0)b.className=a;else if(b.className!==a){var d=b.className.split(/ +/);if(d.indexOf(a)==-1)d.push(a),b.className=d.join(\" \").replace(/^\\s+/,\"\").replace(/\\s+$/,\"\")}return f},removeClass:function(b,a){if(a){if(b.className!==void 0)if(b.className===a)b.removeAttribute(\"class\");else{var d=b.className.split(/ +/),\nc=d.indexOf(a);if(c!=-1)d.splice(c,1),b.className=d.join(\" \")}}else b.className=void 0;return f},hasClass:function(a,d){return RegExp(\"(?:^|\\\\s+)\"+d+\"(?:\\\\s+|$)\").test(a.className)||false},getWidth:function(b){b=getComputedStyle(b);return a(b[\"border-left-width\"])+a(b[\"border-right-width\"])+a(b[\"padding-left\"])+a(b[\"padding-right\"])+a(b.width)},getHeight:function(b){b=getComputedStyle(b);return a(b[\"border-top-width\"])+a(b[\"border-bottom-width\"])+a(b[\"padding-top\"])+a(b[\"padding-bottom\"])+a(b.height)},\ngetOffset:function(a){var d={left:0,top:0};if(a.offsetParent){do d.left+=a.offsetLeft,d.top+=a.offsetTop;while(a=a.offsetParent)}return d},isActive:function(a){return a===document.activeElement&&(a.type||a.href)}};return f}(dat.utils.common);\ndat.controllers.OptionController=function(e,a,c){var d=function(f,b,e){d.superclass.call(this,f,b);var h=this;this.__select=document.createElement(\"select\");if(c.isArray(e)){var j={};c.each(e,function(a){j[a]=a});e=j}c.each(e,function(a,b){var d=document.createElement(\"option\");d.innerHTML=b;d.setAttribute(\"value\",a);h.__select.appendChild(d)});this.updateDisplay();a.bind(this.__select,\"change\",function(){h.setValue(this.options[this.selectedIndex].value)});this.domElement.appendChild(this.__select)};\nd.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue());return a},updateDisplay:function(){this.__select.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);\ndat.controllers.NumberController=function(e,a){var c=function(d,f,b){c.superclass.call(this,d,f);b=b||{};this.__min=b.min;this.__max=b.max;this.__step=b.step;d=this.__impliedStep=a.isUndefined(this.__step)?this.initialValue==0?1:Math.pow(10,Math.floor(Math.log(this.initialValue)/Math.LN10))/10:this.__step;d=d.toString();this.__precision=d.indexOf(\".\")>-1?d.length-d.indexOf(\".\")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&a<this.__min)a=this.__min;\nelse if(this.__max!==void 0&&a>this.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common);\ndat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,\"mousemove\",j);a.unbind(window,\"mouseup\",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement(\"input\");this.__input.setAttribute(\"type\",\"text\");a.bind(this.__input,\"change\",h);\na.bind(this.__input,\"blur\",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,\"mousedown\",function(b){a.bind(window,\"mousemove\",j);a.bind(window,\"mouseup\",m);o=b.clientY});a.bind(this.__input,\"keydown\",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input,\nb;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common);\ndat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,\"mousemove\",o);a.unbind(window,\"mouseup\",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement(\"div\");\nthis.__foreground=document.createElement(\"div\");a.bind(this.__background,\"mousedown\",function(b){a.bind(window,\"mousemove\",o);a.bind(window,\"mouseup\",y);o(b)});a.addClass(this.__background,\"slider\");a.addClass(this.__foreground,\"slider-fg\");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width=\n(this.getValue()-this.__min)/(this.__max-this.__min)*100+\"%\";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,\".slider {\\n  box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\\n  height: 1em;\\n  border-radius: 1em;\\n  background-color: #eee;\\n  padding: 0 0.5em;\\n  overflow: hidden;\\n}\\n\\n.slider-fg {\\n  padding: 1px 0 2px 0;\\n  background-color: #aaa;\\n  height: 1em;\\n  margin-left: -0.5em;\\n  padding-right: 0.5em;\\n  border-radius: 1em 0 0 1em;\\n}\\n\\n.slider-fg:after {\\n  display: inline-block;\\n  border-radius: 1em;\\n  background-color: #fff;\\n  border:  1px solid #aaa;\\n  content: '';\\n  float: right;\\n  margin-right: -1em;\\n  margin-top: -1px;\\n  height: 0.9em;\\n  width: 0.9em;\\n}\");\ndat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement(\"div\");this.__button.innerHTML=e===void 0?\"Fire\":e;a.bind(this.__button,\"click\",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,\"button\");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this,\nthis.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);\ndat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement(\"input\");this.__checkbox.setAttribute(\"type\",\"checkbox\");a.bind(this.__checkbox,\"change\",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&&\nthis.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute(\"checked\",\"checked\"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common);\ndat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a=\"0\"+a;return\"#\"+a}else return\"rgba(\"+Math.round(a.r)+\",\"+Math.round(a.g)+\",\"+Math.round(a.b)+\",\"+a.a+\")\"}}(dat.utils.common);\ndat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:\"HEX\",hex:parseInt(\"0x\"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:\"HEX\",hex:parseInt(\"0x\"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\\(\\s*(.+)\\s*,\\s*(.+)\\s*,\\s*(.+)\\s*\\)/);\nreturn a===null?false:{space:\"RGB\",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\\(\\s*(.+)\\s*,\\s*(.+)\\s*,\\s*(.+)\\s*\\,\\s*(.+)\\s*\\)/);return a===null?false:{space:\"RGB\",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:\"HEX\",hex:a,conversionName:\"HEX\"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!=\n3?false:{space:\"RGB\",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:\"RGB\",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:\"RGB\",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&&\na.isNumber(b.g)&&a.isNumber(b.b)?{space:\"RGB\",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:\"HSV\",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:\"HSV\",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d=\nfalse;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common);\ndat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error(\"Object \"+b+' has no property \"'+r+'\"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,\"c\");r=document.createElement(\"span\");g.addClass(r,\"property-name\");r.innerHTML=b.property;var e=document.createElement(\"div\");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW);\ng.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement(\"li\");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property,\n{before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each([\"updateDisplay\",\"onChange\",\"onFinishChange\"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}});\ng.addClass(d,\"has-slider\");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,\"click\",function(){g.fakeEvent(c.__checkbox,\"click\")}),g.bind(c.__checkbox,\"click\",function(a){a.stopPropagation()});\nelse if(c instanceof n)g.bind(d,\"click\",function(){g.fakeEvent(c.__button,\"click\")}),g.bind(d,\"mouseover\",function(){g.addClass(c.__button,\"hover\")}),g.bind(d,\"mouseout\",function(){g.removeClass(c.__button,\"hover\")});else if(c instanceof l)g.addClass(d,\"color\"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)}\nfunction t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement(\"li\");g.addClass(a.domElement,\n\"has-save\");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,\"save-row\");var c=document.createElement(\"span\");c.innerHTML=\"&nbsp;\";g.addClass(c,\"button gears\");var d=document.createElement(\"span\");d.innerHTML=\"Save\";g.addClass(d,\"button\");g.addClass(d,\"save\");var e=document.createElement(\"span\");e.innerHTML=\"New\";g.addClass(e,\"button\");g.addClass(e,\"save-as\");var f=document.createElement(\"span\");f.innerHTML=\"Revert\";g.addClass(f,\"button\");g.addClass(f,\"revert\");var m=a.__preset_select=document.createElement(\"select\");\na.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,\"change\",function(){for(var b=0;b<a.__preset_select.length;b++)a.__preset_select[b].innerHTML=a.__preset_select[b].value;a.preset=this.value});b.appendChild(m);b.appendChild(c);b.appendChild(d);b.appendChild(e);b.appendChild(f);if(u){var b=document.getElementById(\"dg-save-locally\"),l=document.getElementById(\"dg-local-explain\");b.style.display=\"block\";b=document.getElementById(\"dg-local-storage\");\nlocalStorage.getItem(document.location.href+\".isLocal\")===\"true\"&&b.setAttribute(\"checked\",\"checked\");var o=function(){l.style.display=a.useLocalStorage?\"block\":\"none\"};o();g.bind(b,\"change\",function(){a.useLocalStorage=!a.useLocalStorage;o()})}var h=document.getElementById(\"dg-new-constructor\");g.bind(h,\"keydown\",function(a){a.metaKey&&(a.which===67||a.keyCode==67)&&x.hide()});g.bind(c,\"click\",function(){h.innerHTML=JSON.stringify(a.getSaveObject(),void 0,2);x.show();h.focus();h.select()});g.bind(d,\n\"click\",function(){a.save()});g.bind(e,\"click\",function(){var b=prompt(\"Enter a new preset name.\");b&&a.saveAs(b)});g.bind(f,\"click\",function(){a.revert()})}function J(a){function b(f){f.preventDefault();e=f.clientX;g.addClass(a.__closeButton,k.CLASS_DRAG);g.bind(window,\"mousemove\",c);g.bind(window,\"mouseup\",d);return false}function c(b){b.preventDefault();a.width+=e-b.clientX;a.onResize();e=b.clientX;return false}function d(){g.removeClass(a.__closeButton,k.CLASS_DRAG);g.unbind(window,\"mousemove\",\nc);g.unbind(window,\"mouseup\",d)}a.__resize_handle=document.createElement(\"div\");i.extend(a.__resize_handle.style,{width:\"6px\",marginLeft:\"-3px\",height:\"200px\",cursor:\"ew-resize\",position:\"absolute\"});var e;g.bind(a.__resize_handle,\"mousedown\",b);g.bind(a.__closeButton,\"mousedown\",b);a.domElement.insertBefore(a.__resize_handle,a.domElement.firstElementChild)}function D(a,b){a.domElement.style.width=b+\"px\";if(a.__save_row&&a.autoPlace)a.__save_row.style.width=b+\"px\";if(a.__closeButton)a.__closeButton.style.width=\nb+\"px\"}function z(a,b){var c={};i.each(a.__rememberedObjects,function(d,e){var f={};i.each(a.__rememberedObjectIndecesToControllers[e],function(a,c){f[c]=b?a.initialValue:a.getValue()});c[e]=f});return c}function C(a,b,c){var d=document.createElement(\"option\");d.innerHTML=b;d.value=b;a.__preset_select.appendChild(d);if(c)a.__preset_select.selectedIndex=a.__preset_select.length-1}function B(a,b){var c=a.__preset_select[a.__preset_select.selectedIndex];c.innerHTML=b?c.value+\"*\":c.value}function E(a){a.length!=\n0&&o(function(){E(a)});i.each(a,function(a){a.updateDisplay()})}e.inject(c);var w=\"Default\",u;try{u=\"localStorage\"in window&&window.localStorage!==null}catch(K){u=false}var x,F=true,v,A=false,G=[],k=function(a){function b(){localStorage.setItem(document.location.href+\".gui\",JSON.stringify(d.getSaveObject()))}function c(){var a=d.getRoot();a.width+=1;i.defer(function(){a.width-=1})}var d=this;this.domElement=document.createElement(\"div\");this.__ul=document.createElement(\"ul\");this.domElement.appendChild(this.__ul);\ng.addClass(this.domElement,\"dg\");this.__folders={};this.__controllers=[];this.__rememberedObjects=[];this.__rememberedObjectIndecesToControllers=[];this.__listening=[];a=a||{};a=i.defaults(a,{autoPlace:true,width:k.DEFAULT_WIDTH});a=i.defaults(a,{resizable:a.autoPlace,hideable:a.autoPlace});if(i.isUndefined(a.load))a.load={preset:w};else if(a.preset)a.load.preset=a.preset;i.isUndefined(a.parent)&&a.hideable&&G.push(this);a.resizable=i.isUndefined(a.parent)&&a.resizable;if(a.autoPlace&&i.isUndefined(a.scrollable))a.scrollable=\ntrue;var e=u&&localStorage.getItem(document.location.href+\".isLocal\")===\"true\";Object.defineProperties(this,{parent:{get:function(){return a.parent}},scrollable:{get:function(){return a.scrollable}},autoPlace:{get:function(){return a.autoPlace}},preset:{get:function(){return d.parent?d.getRoot().preset:a.load.preset},set:function(b){d.parent?d.getRoot().preset=b:a.load.preset=b;for(b=0;b<this.__preset_select.length;b++)if(this.__preset_select[b].value==this.preset)this.__preset_select.selectedIndex=\nb;d.revert()}},width:{get:function(){return a.width},set:function(b){a.width=b;D(d,b)}},name:{get:function(){return a.name},set:function(b){a.name=b;if(m)m.innerHTML=a.name}},closed:{get:function(){return a.closed},set:function(b){a.closed=b;a.closed?g.addClass(d.__ul,k.CLASS_CLOSED):g.removeClass(d.__ul,k.CLASS_CLOSED);this.onResize();if(d.__closeButton)d.__closeButton.innerHTML=b?k.TEXT_OPEN:k.TEXT_CLOSED}},load:{get:function(){return a.load}},useLocalStorage:{get:function(){return e},set:function(a){u&&\n((e=a)?g.bind(window,\"unload\",b):g.unbind(window,\"unload\",b),localStorage.setItem(document.location.href+\".isLocal\",a))}}});if(i.isUndefined(a.parent)){a.closed=false;g.addClass(this.domElement,k.CLASS_MAIN);g.makeSelectable(this.domElement,false);if(u&&e){d.useLocalStorage=true;var f=localStorage.getItem(document.location.href+\".gui\");if(f)a.load=JSON.parse(f)}this.__closeButton=document.createElement(\"div\");this.__closeButton.innerHTML=k.TEXT_CLOSED;g.addClass(this.__closeButton,k.CLASS_CLOSE_BUTTON);\nthis.domElement.appendChild(this.__closeButton);g.bind(this.__closeButton,\"click\",function(){d.closed=!d.closed})}else{if(a.closed===void 0)a.closed=true;var m=document.createTextNode(a.name);g.addClass(m,\"controller-name\");f=s(d,m);g.addClass(this.__ul,k.CLASS_CLOSED);g.addClass(f,\"title\");g.bind(f,\"click\",function(a){a.preventDefault();d.closed=!d.closed;return false});if(!a.closed)this.closed=false}a.autoPlace&&(i.isUndefined(a.parent)&&(F&&(v=document.createElement(\"div\"),g.addClass(v,\"dg\"),g.addClass(v,\nk.CLASS_AUTO_PLACE_CONTAINER),document.body.appendChild(v),F=false),v.appendChild(this.domElement),g.addClass(this.domElement,k.CLASS_AUTO_PLACE)),this.parent||D(d,a.width));g.bind(window,\"resize\",function(){d.onResize()});g.bind(this.__ul,\"webkitTransitionEnd\",function(){d.onResize()});g.bind(this.__ul,\"transitionend\",function(){d.onResize()});g.bind(this.__ul,\"oTransitionEnd\",function(){d.onResize()});this.onResize();a.resizable&&J(this);d.getRoot();a.parent||c()};k.toggleHide=function(){A=!A;i.each(G,\nfunction(a){a.domElement.style.zIndex=A?-999:999;a.domElement.style.opacity=A?0:1})};k.CLASS_AUTO_PLACE=\"a\";k.CLASS_AUTO_PLACE_CONTAINER=\"ac\";k.CLASS_MAIN=\"main\";k.CLASS_CONTROLLER_ROW=\"cr\";k.CLASS_TOO_TALL=\"taller-than-window\";k.CLASS_CLOSED=\"closed\";k.CLASS_CLOSE_BUTTON=\"close-button\";k.CLASS_DRAG=\"drag\";k.DEFAULT_WIDTH=245;k.TEXT_CLOSED=\"Close Controls\";k.TEXT_OPEN=\"Open Controls\";g.bind(window,\"keydown\",function(a){document.activeElement.type!==\"text\"&&(a.which===72||a.keyCode==72)&&k.toggleHide()},\nfalse);i.extend(k.prototype,{add:function(a,b){return q(this,a,b,{factoryArgs:Array.prototype.slice.call(arguments,2)})},addColor:function(a,b){return q(this,a,b,{color:true})},remove:function(a){this.__ul.removeChild(a.__li);this.__controllers.slice(this.__controllers.indexOf(a),1);var b=this;i.defer(function(){b.onResize()})},destroy:function(){this.autoPlace&&v.removeChild(this.domElement)},addFolder:function(a){if(this.__folders[a]!==void 0)throw Error('You already have a folder in this GUI by the name \"'+\na+'\"');var b={name:a,parent:this};b.autoPlace=this.autoPlace;if(this.load&&this.load.folders&&this.load.folders[a])b.closed=this.load.folders[a].closed,b.load=this.load.folders[a];b=new k(b);this.__folders[a]=b;a=s(this,b.domElement);g.addClass(a,\"folder\");return b},open:function(){this.closed=false},close:function(){this.closed=true},onResize:function(){var a=this.getRoot();if(a.scrollable){var b=g.getOffset(a.__ul).top,c=0;i.each(a.__ul.childNodes,function(b){a.autoPlace&&b===a.__save_row||(c+=\ng.getHeight(b))});window.innerHeight-b-20<c?(g.addClass(a.domElement,k.CLASS_TOO_TALL),a.__ul.style.height=window.innerHeight-b-20+\"px\"):(g.removeClass(a.domElement,k.CLASS_TOO_TALL),a.__ul.style.height=\"auto\")}a.__resize_handle&&i.defer(function(){a.__resize_handle.style.height=a.__ul.offsetHeight+\"px\"});if(a.__closeButton)a.__closeButton.style.width=a.width+\"px\"},remember:function(){if(i.isUndefined(x))x=new y,x.domElement.innerHTML=a;if(this.parent)throw Error(\"You can only call remember on a top level GUI.\");\nvar b=this;i.each(Array.prototype.slice.call(arguments),function(a){b.__rememberedObjects.length==0&&I(b);b.__rememberedObjects.indexOf(a)==-1&&b.__rememberedObjects.push(a)});this.autoPlace&&D(this,this.width)},getRoot:function(){for(var a=this;a.parent;)a=a.parent;return a},getSaveObject:function(){var a=this.load;a.closed=this.closed;if(this.__rememberedObjects.length>0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b,\nc){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders,\nfunction(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'<div id=\"dg-save\" class=\"dg dialogue\">\\n\\n  Here\\'s the new load parameter for your <code>GUI</code>\\'s constructor:\\n\\n  <textarea id=\"dg-new-constructor\"></textarea>\\n\\n  <div id=\"dg-save-locally\">\\n\\n    <input id=\"dg-local-storage\" type=\"checkbox\"/> Automatically save\\n    values to <code>localStorage</code> on exit.\\n\\n    <div id=\"dg-local-explain\">The values saved to <code>localStorage</code> will\\n      override those passed to <code>dat.GUI</code>\\'s constructor. This makes it\\n      easier to work incrementally, but <code>localStorage</code> is fragile,\\n      and your friends may not see the same values you do.\\n      \\n    </div>\\n    \\n  </div>\\n\\n</div>',\n\".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\\n\",\ndat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,\"\");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d=\nfunction(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement(\"input\");this.__input.setAttribute(\"type\",\"text\");a.bind(this.__input,\"keyup\",e);a.bind(this.__input,\"change\",e);a.bind(this.__input,\"blur\",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,\"keydown\",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,\ne.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController,\ndat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background=\"\";f.each(j,function(e){a.style.cssText+=\"background: \"+e+\"linear-gradient(\"+b+\", \"+c+\" 0%, \"+d+\" 100%); \"})}function n(a){a.style.background=\"\";a.style.cssText+=\"background: -moz-linear-gradient(top,  #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);\";a.style.cssText+=\"background: -webkit-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);\";\na.style.cssText+=\"background: -o-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);\";a.style.cssText+=\"background: -ms-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);\";a.style.cssText+=\"background: linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);\"}var h=function(e,l){function o(b){q(b);a.bind(window,\"mousemove\",q);a.bind(window,\n\"mouseup\",j)}function j(){a.unbind(window,\"mousemove\",q);a.unbind(window,\"mouseup\",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,\"mousemove\",s);a.unbind(window,\"mouseup\",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=\n1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement(\"div\");a.makeSelectable(this.domElement,\nfalse);this.__selector=document.createElement(\"div\");this.__selector.className=\"selector\";this.__saturation_field=document.createElement(\"div\");this.__saturation_field.className=\"saturation-field\";this.__field_knob=document.createElement(\"div\");this.__field_knob.className=\"field-knob\";this.__field_knob_border=\"2px solid \";this.__hue_knob=document.createElement(\"div\");this.__hue_knob.className=\"hue-knob\";this.__hue_field=document.createElement(\"div\");this.__hue_field.className=\"hue-field\";this.__input=\ndocument.createElement(\"input\");this.__input.type=\"text\";this.__input_textShadow=\"0 1px 1px \";a.bind(this.__input,\"keydown\",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,\"blur\",g);a.bind(this.__selector,\"mousedown\",function(){a.addClass(this,\"drag\").bind(window,\"mouseup\",function(){a.removeClass(p.__selector,\"drag\")})});var t=document.createElement(\"div\");f.extend(this.__selector.style,{width:\"122px\",height:\"102px\",padding:\"3px\",backgroundColor:\"#222\",boxShadow:\"0px 1px 3px rgba(0,0,0,0.3)\"});\nf.extend(this.__field_knob.style,{position:\"absolute\",width:\"12px\",height:\"12px\",border:this.__field_knob_border+(this.__color.v<0.5?\"#fff\":\"#000\"),boxShadow:\"0px 1px 3px rgba(0,0,0,0.5)\",borderRadius:\"12px\",zIndex:1});f.extend(this.__hue_knob.style,{position:\"absolute\",width:\"15px\",height:\"2px\",borderRight:\"4px solid #fff\",zIndex:1});f.extend(this.__saturation_field.style,{width:\"100px\",height:\"100px\",border:\"1px solid #555\",marginRight:\"3px\",display:\"inline-block\",cursor:\"pointer\"});f.extend(t.style,\n{width:\"100%\",height:\"100%\",background:\"none\"});b(t,\"top\",\"rgba(0,0,0,0)\",\"#000\");f.extend(this.__hue_field.style,{width:\"15px\",height:\"100px\",display:\"inline-block\",border:\"1px solid #555\",cursor:\"ns-resize\"});n(this.__hue_field);f.extend(this.__input.style,{outline:\"none\",textAlign:\"center\",color:\"#fff\",border:0,fontWeight:\"bold\",textShadow:this.__input_textShadow+\"rgba(0,0,0,0.7)\"});a.bind(this.__saturation_field,\"mousedown\",o);a.bind(this.__field_knob,\"mousedown\",o);a.bind(this.__hue_field,\"mousedown\",\nfunction(b){s(b);a.bind(window,\"mousemove\",s);a.bind(window,\"mouseup\",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue());\nif(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+\"px\",marginTop:100*(1-this.__color.v)-7+\"px\",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+\n\"rgb(\"+h+\",\"+h+\",\"+h+\")\"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+\"px\";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,\"left\",\"#fff\",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:\"rgb(\"+h+\",\"+h+\",\"+h+\")\",textShadow:this.__input_textShadow+\"rgba(\"+j+\",\"+j+\",\"+j+\",.7)\"})}});var j=[\"-moz-\",\"-o-\",\"-webkit-\",\"-ms-\",\"\"];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a,\nb,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space===\"RGB\")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!==\"RGB\")n(this,b,c),this.__state.space=\"RGB\";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space===\"HSV\")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!==\"HSV\")h(this),this.__state.space=\"HSV\";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space===\n\"HEX\")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space===\"HSV\")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw\"Corrupted color state\";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw\"Failed to interpret color arguments\";this.__state.a=this.__state.a||\n1};j.COMPONENTS=\"r,g,b,h,s,v,hex,a\".split(\",\");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,\"r\",2);f(j.prototype,\"g\",1);f(j.prototype,\"b\",0);b(j.prototype,\"h\");b(j.prototype,\"s\");b(j.prototype,\"v\");Object.defineProperty(j.prototype,\"a\",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,\"hex\",{get:function(){if(!this.__state.space!==\"HEX\")this.__state.hex=\na.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space=\"HEX\";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0};\na=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<<e)}}}(),dat.color.toString,dat.utils.common),dat.color.interpret,dat.utils.common),dat.utils.requestAnimationFrame=function(){return window.webkitRequestAnimationFrame||\nwindow.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1E3/60)}}(),dat.dom.CenteredDiv=function(e,a){var c=function(){this.backgroundElement=document.createElement(\"div\");a.extend(this.backgroundElement.style,{backgroundColor:\"rgba(0,0,0,0.8)\",top:0,left:0,display:\"none\",zIndex:\"1000\",opacity:0,WebkitTransition:\"opacity 0.2s linear\"});e.makeFullscreen(this.backgroundElement);this.backgroundElement.style.position=\"fixed\";this.domElement=\ndocument.createElement(\"div\");a.extend(this.domElement.style,{position:\"fixed\",display:\"none\",zIndex:\"1001\",opacity:0,WebkitTransition:\"-webkit-transform 0.2s ease-out, opacity 0.2s linear\"});document.body.appendChild(this.backgroundElement);document.body.appendChild(this.domElement);var c=this;e.bind(this.backgroundElement,\"click\",function(){c.hide()})};c.prototype.show=function(){var c=this;this.backgroundElement.style.display=\"block\";this.domElement.style.display=\"block\";this.domElement.style.opacity=\n0;this.domElement.style.webkitTransform=\"scale(1.1)\";this.layout();a.defer(function(){c.backgroundElement.style.opacity=1;c.domElement.style.opacity=1;c.domElement.style.webkitTransform=\"scale(1)\"})};c.prototype.hide=function(){var a=this,c=function(){a.domElement.style.display=\"none\";a.backgroundElement.style.display=\"none\";e.unbind(a.domElement,\"webkitTransitionEnd\",c);e.unbind(a.domElement,\"transitionend\",c);e.unbind(a.domElement,\"oTransitionEnd\",c)};e.bind(this.domElement,\"webkitTransitionEnd\",\nc);e.bind(this.domElement,\"transitionend\",c);e.bind(this.domElement,\"oTransitionEnd\",c);this.backgroundElement.style.opacity=0;this.domElement.style.opacity=0;this.domElement.style.webkitTransform=\"scale(1.1)\"};c.prototype.layout=function(){this.domElement.style.left=window.innerWidth/2-e.getWidth(this.domElement)/2+\"px\";this.domElement.style.top=window.innerHeight/2-e.getHeight(this.domElement)/2+\"px\"};return c}(dat.dom.dom,dat.utils.common),dat.dom.dom,dat.utils.common);;\n\n// Generated by CoffeeScript 1.3.3\n(function() {\n  var log_count, now, start;\n\n  if (window.performance) {\n    if (window.performance.now) {\n      now = function() {\n        return window.performance.now();\n      };\n    } else if (window.performance.webkitNow) {\n      now = function() {\n        return window.performance.webkitNow();\n      };\n    } else if (window.performance.mozNow) {\n      now = function() {\n        return window.performance.mozNow();\n      };\n    } else if (window.performance.oNow) {\n      now = function() {\n        return window.performance.oNow();\n      };\n    } else {\n      now = function() {\n        return Date.now();\n      };\n    }\n  } else {\n    now = function() {\n      return Date.now();\n    };\n  }\n\n  start = now();\n\n  window.gettime = function() {\n    return (now() - start) / 1000;\n  };\n\n  if (!window.requestAnimationFrame) {\n    if (window.webkitRequestAnimationFrame) {\n      window.requestAnimationFrame = window.webkitRequestAnimationFrame;\n    } else if (window.mozRequestAnimationFrame) {\n      window.requestAnimationFrame = window.mozRequestAnimationFrame;\n    } else if (window.oRequestAnimationFrame) {\n      window.requestAnimationFrame = window.oRequestAnimationFrame;\n    } else {\n      window.requestAnimationFrame = function(fun) {\n        return setTimeout(fun, 1000 / 30);\n      };\n    }\n  }\n\n  window.URL = window.URL || window.mozURL || window.webkitURL || window.oURL;\n\n  window.BlobBuilder = window.BlobBuilder || window.MozBlobBuilder || window.WebKitBlobBuilder || window.OBlobBuilder;\n\n  log_count = 0;\n\n  window.console.logN = function(n) {\n    var args;\n    if (log_count < n) {\n      log_count += 1;\n      args = [].slice.call(arguments, 1);\n      return console.log.apply(console, args);\n    }\n  };\n\n}).call(this);\n;\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar Stats = function () {\n\n\tvar startTime = Date.now(), prevTime = startTime;\n\tvar ms = 0, msMin = 1000, msMax = 0;\n\tvar fps = 0, fpsMin = 1000, fpsMax = 0;\n\tvar frames = 0, mode = 0;\t\n\n\tvar container = document.createElement( 'div' );\n\tcontainer.id = 'stats';\n\tcontainer.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false );\n\tcontainer.style.cssText = 'width:80px;opacity:0.9;cursor:pointer';\n\n\tvar fpsDiv = document.createElement( 'div' );\n\tfpsDiv.id = 'fps';\n\tfpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002';\n\tcontainer.appendChild( fpsDiv );\n\n\tvar fpsText = document.createElement( 'div' );\n\tfpsText.id = 'fpsText';\n\tfpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n\tfpsText.innerHTML = 'FPS';\n\tfpsDiv.appendChild( fpsText );\n\n\tvar fpsGraph = document.createElement( 'div' );\n\tfpsGraph.id = 'fpsGraph';\n\tfpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff';\n\tfpsDiv.appendChild( fpsGraph );\n\n\twhile ( fpsGraph.children.length < 74 ) {\n\n\t\tvar bar = document.createElement( 'span' );\n\t\tbar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113';\n\t\tfpsGraph.appendChild( bar );\n\n\t}\n\n\tvar msDiv = document.createElement( 'div' );\n\tmsDiv.id = 'ms';\n\tmsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none';\n\tcontainer.appendChild( msDiv );\n\n\tvar msText = document.createElement( 'div' );\n\tmsText.id = 'msText';\n\tmsText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px';\n\tmsText.innerHTML = 'MS';\n\tmsDiv.appendChild( msText );\n\n\tvar msGraph = document.createElement( 'div' );\n\tmsGraph.id = 'msGraph';\n\tmsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0';\n\tmsDiv.appendChild( msGraph );\n\n\twhile ( msGraph.children.length < 74 ) {\n\n\t\tvar bar = document.createElement( 'span' );\n\t\tbar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131';\n\t\tmsGraph.appendChild( bar );\n\n\t}\n\n\tvar setMode = function ( value ) {\n\n\t\tmode = value;\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase 0:\n\t\t\t\tfpsDiv.style.display = 'block';\n\t\t\t\tmsDiv.style.display = 'none';\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tfpsDiv.style.display = 'none';\n\t\t\t\tmsDiv.style.display = 'block';\n\t\t\t\tbreak;\n\t\t}\n\n\t}\n\n\tvar updateGraph = function ( dom, value ) {\n\n\t\tvar child = dom.appendChild( dom.firstChild );\n\t\tchild.style.height = value + 'px';\n\n\t}\n\n\treturn {\n\n\t\tdomElement: container,\n\n\t\tsetMode: setMode,\n\n\t\tbegin: function () {\n\n\t\t\tstartTime = Date.now();\n\n\t\t},\n\n\t\tend: function () {\n\n\t\t\tvar time = Date.now();\n\n\t\t\tms = time - startTime;\n\t\t\tmsMin = Math.min( msMin, ms );\n\t\t\tmsMax = Math.max( msMax, ms );\n\n\t\t\tmsText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')';\n\t\t\tupdateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) );\n\n\t\t\tframes ++;\n\n\t\t\tif ( time > prevTime + 1000 ) {\n\n\t\t\t\tfps = Math.round( ( frames * 1000 ) / ( time - prevTime ) );\n\t\t\t\tfpsMin = Math.min( fpsMin, fps );\n\t\t\t\tfpsMax = Math.max( fpsMax, fps );\n\n\t\t\t\tfpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')';\n\t\t\t\tupdateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) );\n\n\t\t\t\tprevTime = time;\n\t\t\t\tframes = 0;\n\n\t\t\t}\n\n\t\t\treturn time;\n\n\t\t},\n\n\t\tupdate: function () {\n\n\t\t\tstartTime = this.end();\n\t\t\t\n\t\t}\n\n\t}\n\t\n};\n;\n\n// Generated by CoffeeScript 1.3.3\n(function() {\n  var fs, getBuffer, getJSON, isImage, makeBlob, makeURL, resolvePath;\n\n  fs = {};\n\n  makeURL = function(blob) {\n    return URL.createObjectURL(blob);\n  };\n\n  makeBlob = function(data, type) {\n    var blob;\n    blob = new Blob([data], {\n      type: type\n    });\n    return blob;\n  };\n\n  window.getURL = function(data, mime) {\n    var blob;\n    blob = makeBlob(data, mime);\n    return makeURL(blob);\n  };\n\n  resolvePath = function(base, path) {\n    if (path[0] === '/') {\n      return path;\n    } else {\n      path = path.split('/');\n      if (base === '/') {\n        base = [''];\n      } else {\n        base = base.split('/');\n      }\n      while (base.length > 0 && path.length > 0 && path[0] === '..') {\n        base.pop();\n        path.shift();\n      }\n      if (base.length === 0 || path.length === 0 || base[0] !== '') {\n        throw \"Invalid path: \" + (base.join('/')) + \"/\" + (path.join('/'));\n      }\n      return \"\" + (base.join('/')) + \"/\" + (path.join('/'));\n    }\n  };\n\n  getJSON = function(url, callback) {\n    var request;\n    request = new XMLHttpRequest();\n    request.open('GET', url, true);\n    request.onload = function() {\n      return callback(JSON.parse(request.response));\n    };\n    return request.send();\n  };\n\n  getBuffer = function(url, progress, callback) {\n    var request;\n    request = new XMLHttpRequest();\n    request.open('GET', url, true);\n    request.responseType = 'arraybuffer';\n    request.onload = function() {\n      return callback(request.response);\n    };\n    request.onprogress = function(event) {\n      if (event.lengthComputable) {\n        return progress(event.loaded / event.total);\n      }\n    };\n    return request.send();\n  };\n\n  isImage = function(path) {\n    return path.match('\\.jpg$|\\.jpeg|\\.gif$|\\.png');\n  };\n\n  window.loader = {\n    resolvePath: resolvePath,\n    main: function() {\n      var main;\n      main = this.require('main');\n      if (main.main) {\n        return main.main();\n      } else {\n        throw 'Main function is not defined in main module.';\n      }\n    },\n    define: function(path, code) {\n      var dirname, folder, get, require;\n      dirname = path.split('/');\n      dirname.pop();\n      dirname = dirname.join('/');\n      require = function(modpath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, modpath);\n        node = fs[\"\" + abspath + \".js\"];\n        if (!node) {\n          node = fs[\"\" + abspath + \"/module.js\"];\n        }\n        if (!node) {\n          throw \"Module not found: \" + abspath;\n        }\n        if (!node.value) {\n          node.create();\n        }\n        return node.value;\n      };\n      get = function(respath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, respath);\n        node = fs[abspath];\n        if (!node) {\n          throw \"Resource not found: \" + abspath;\n        }\n        return node;\n      };\n      get.exists = function(respath) {\n        var abspath, node;\n        abspath = resolvePath(dirname, respath);\n        node = fs[abspath];\n        return node !== void 0;\n      };\n      folder = get.folder = function(folderpath) {\n        var folder_abs;\n        folder_abs = resolvePath(dirname, folderpath);\n        return {\n          path: folder_abs,\n          name: folder_abs.split('/')[folder_abs.split('/').length - 1],\n          get: function(respath) {\n            var node, nodepath;\n            nodepath = resolvePath(folder_abs, respath);\n            node = fs[nodepath];\n            if (!node) {\n              throw \"Resource not found: \" + nodepath;\n            }\n            return node;\n          },\n          exists: function(respath) {\n            var nodepath;\n            nodepath = resolvePath(folder_abs, respath);\n            return fs[nodepath] !== void 0;\n          },\n          listdir: function(respath) {\n            var match, name, nodepath, result, translated, _i, _len;\n            if (respath) {\n              nodepath = resolvepath(folder_abs, respath);\n            } else {\n              nodepath = folder_abs;\n            }\n            result = [];\n            for (name in fs) {\n              match = name.match(\"\" + folder_abs + \"/[a-zA-Z0-9-\\.]+\");\n              if (match) {\n                match = match[0];\n                if (result.indexOf(match) === -1) {\n                  result.push(match);\n                }\n              }\n            }\n            translated = [];\n            for (_i = 0, _len = result.length; _i < _len; _i++) {\n              name = result[_i];\n              if (name.match(/\\.[a-z]+$/)) {\n                translated.push(name);\n              } else {\n                translated.push(folder(name));\n              }\n            }\n            return translated;\n          }\n        };\n      };\n      get.listdir = function(respath, match) {\n        var abspath, name, result;\n        if (respath) {\n          abspath = resolvePath(dirname, respath);\n        } else {\n          abspath = dirname;\n        }\n        result = [];\n        for (name in fs) {\n          if (name.search(abspath) === 0) {\n            if (match) {\n              if (name.match(match)) {\n                result.push(name);\n              }\n            } else {\n              result.push(name);\n            }\n          }\n        }\n        return result;\n      };\n      return fs[path] = {\n        path: path,\n        type: 'code',\n        data: code,\n        create: function() {\n          var retval;\n          this.value = {};\n          retval = code(this.value, require, get);\n          if (retval) {\n            return this.value = retval;\n          }\n        }\n      };\n    },\n    require: function(modpath) {\n      var abspath, node;\n      abspath = resolvePath('/', modpath);\n      node = fs[\"\" + abspath + \".js\"];\n      if (!node) {\n        node = fs[\"\" + abspath + \"/module.js\"];\n      }\n      if (!node) {\n        throw \"Module not found: \" + abspath;\n      }\n      if (!node.value) {\n        node.create();\n      }\n      return node.value;\n    },\n    loadPack: function(_arg) {\n      var files, hooks, loaded, progress, url;\n      url = _arg.url, progress = _arg.progress, loaded = _arg.loaded;\n      files = {};\n      hooks = this.hooks;\n      return getBuffer(url, (function(factor) {\n        if (progress) {\n          return progress(factor * 0.5, 'network');\n        }\n      }), function(data) {\n        var decoded, decoding, doLoad, i, info, length, metadata, name, result, _i;\n        decoding = 0;\n        decoded = 0;\n        doLoad = function(name, info) {\n          var decode, dst, matcher, src, storage;\n          if (typeof info === 'object' && info.offset !== void 0 && info.size !== void 0) {\n            storage = new ArrayBuffer(info.size);\n            dst = new Uint8Array(storage);\n            src = new Uint8Array(data, 8 + length + info.offset, info.size);\n            dst.set(src);\n            dst = dst.buffer;\n            if (hooks) {\n              for (matcher in hooks) {\n                decode = hooks[matcher];\n                if (name.match(matcher)) {\n                  decoding += 1;\n                  decode(name, dst, function(result) {\n                    decoded += 1;\n                    files[name] = result;\n                    if (progress) {\n                      progress(0.5 + (decoded / decoding) * 0.5, 'decode');\n                    }\n                    if (decoding === decoded && loaded) {\n                      return loaded(files);\n                    }\n                  });\n                  return;\n                }\n              }\n            }\n            return files[name] = dst;\n          } else {\n            if (hooks) {\n              for (matcher in hooks) {\n                decode = hooks[matcher];\n                if (name.match(matcher)) {\n                  decode(name, info, function(result) {\n                    return files[name] = result;\n                  });\n                  return;\n                }\n              }\n            }\n            return files[name] = info;\n          }\n        };\n        length = new Uint32Array(data, 4, 1)[0];\n        metadata = new Uint8Array(data, 8, length);\n        result = '';\n        for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {\n          result += String.fromCharCode(metadata[i]);\n        }\n        result = JSON.parse(result);\n        for (name in result) {\n          info = result[name];\n          doLoad(name, info, data);\n        }\n        if (decoding === decoded && loaded) {\n          return loaded(files);\n        }\n      });\n    },\n    hooks: function(hooks) {\n      this.hooks = hooks;\n      return this;\n    },\n    mount: function(_arg) {\n      var loaded, mountpoint, progress, url;\n      url = _arg.url, mountpoint = _arg.mountpoint, progress = _arg.progress, loaded = _arg.loaded;\n      if (mountpoint == null) {\n        mountpoint = '/';\n      }\n      return this.loadPack({\n        url: url,\n        progress: progress,\n        loaded: function(data) {\n          var name, value;\n          for (name in data) {\n            value = data[name];\n            fs[name] = value;\n          }\n          return loaded(data, fs);\n        }\n      });\n    }\n  };\n\n}).call(this);\n;\n\n// Generated by CoffeeScript 1.3.3\n(function() {\n  var Vec3, Vec4;\n\n  window.Vec3 = Vec3 = (function() {\n\n    Vec3.property('x', {\n      get: function() {\n        return this.data[0];\n      },\n      set: function(val) {\n        return this.data[0] = val;\n      }\n    });\n\n    Vec3.property('y', {\n      get: function() {\n        return this.data[1];\n      },\n      set: function(val) {\n        return this.data[1] = val;\n      }\n    });\n\n    Vec3.property('z', {\n      get: function() {\n        return this.data[2];\n      },\n      set: function(val) {\n        return this.data[2] = val;\n      }\n    });\n\n    Vec3.property('length', {\n      get: function() {\n        return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);\n      }\n    });\n\n    function Vec3(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(3);\n      }\n    }\n\n    Vec3.prototype.sub = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x - other.x;\n      dst.y = this.y - other.y;\n      dst.z = this.z - other.z;\n      return dst;\n    };\n\n    Vec3.prototype.add = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x + other.x;\n      dst.y = this.y + other.y;\n      dst.z = this.z + other.z;\n      return dst;\n    };\n\n    Vec3.prototype.addVal3 = function(x, y, z, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x + x;\n      dst.y = this.y + y;\n      dst.z = this.z + z;\n      return dst;\n    };\n\n    Vec3.prototype.mul = function(scalar, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x * scalar;\n      dst.y = this.y * scalar;\n      dst.z = this.z * scalar;\n      return dst;\n    };\n\n    Vec3.prototype.div = function(scalar, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x / scalar;\n      dst.y = this.y / scalar;\n      dst.z = this.z / scalar;\n      return dst;\n    };\n\n    Vec3.prototype.divVal3 = function(x, y, z, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x / x;\n      dst.y = this.y / y;\n      dst.z = this.z / z;\n      return dst;\n    };\n\n    Vec3.prototype.dot = function(other) {\n      return this.x * other.x + this.y * other.y + this.z * other.z;\n    };\n\n    Vec3.prototype.normalize = function(dst) {\n      var l;\n      if (dst == null) {\n        dst = this;\n      }\n      l = this.length;\n      if (l > 0) {\n        this.mul(1 / this.length, dst);\n      }\n      return dst;\n    };\n\n    Vec3.prototype.set = function(x, y, z) {\n      this.x = x;\n      this.y = y;\n      this.z = z;\n      return this;\n    };\n\n    return Vec3;\n\n  })();\n\n  window.Vec4 = Vec4 = (function() {\n\n    Vec4.property('x', {\n      get: function() {\n        return this.data[0];\n      },\n      set: function(val) {\n        return this.data[0] = val;\n      }\n    });\n\n    Vec4.property('y', {\n      get: function() {\n        return this.data[1];\n      },\n      set: function(val) {\n        return this.data[1] = val;\n      }\n    });\n\n    Vec4.property('z', {\n      get: function() {\n        return this.data[2];\n      },\n      set: function(val) {\n        return this.data[2] = val;\n      }\n    });\n\n    Vec4.property('w', {\n      get: function() {\n        return this.data[3];\n      },\n      set: function(val) {\n        return this.data[3] = val;\n      }\n    });\n\n    function Vec4(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(4);\n      }\n    }\n\n    Vec4.prototype.sub = function(other, dst) {\n      if (dst == null) {\n        dst = this;\n      }\n      dst.x = this.x - other.x;\n      dst.y = this.y - other.y;\n      dst.z = this.z - other.z;\n      dst.w = this.w - other.w;\n      return dst;\n    };\n\n    Vec4.prototype.dot = function(other) {\n      return this.x * other.x + this.y * other.y + this.z * other.z + this.w * other.w;\n    };\n\n    Vec4.prototype.toVec3 = function(dst) {\n      if (dst == null) {\n        dst = new Vec3();\n      }\n      dst.x = this.x;\n      dst.y = this.y;\n      dst.z = this.z;\n      return dst;\n    };\n\n    return Vec4;\n\n  })();\n\n}).call(this);\n;\n\n// Generated by CoffeeScript 1.3.3\n(function() {\n  var Mat3, Mat4, arc, deg, pi, tau;\n\n  pi = Math.PI;\n\n  tau = 2 * pi;\n\n  deg = 360 / tau;\n\n  arc = tau / 360;\n\n  window.Mat3 = Mat3 = (function() {\n\n    function Mat3(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(9);\n      }\n      this.identity();\n    }\n\n    Mat3.prototype.identity = function() {\n      var d;\n      d = this.data;\n      d[0] = 1;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 1;\n      d[5] = 0;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 1;\n      return this;\n    };\n\n    Mat3.prototype.transpose = function() {\n      var a01, a02, a12, d;\n      d = this.data;\n      a01 = d[1];\n      a02 = d[2];\n      a12 = d[5];\n      d[1] = d[3];\n      d[2] = d[6];\n      d[3] = a01;\n      d[5] = d[7];\n      d[6] = a02;\n      d[7] = a12;\n      return this;\n    };\n\n    Mat3.prototype.mulVec3 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      this.mulVal3(vec.x, vec.y, vec.z, dst);\n      return dst;\n    };\n\n    Mat3.prototype.mulVal3 = function(x, y, z, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[3] * y + d[6] * z;\n      dst[1] = d[1] * x + d[4] * y + d[7] * z;\n      dst[2] = d[2] * x + d[5] * y + d[8] * z;\n      return this;\n    };\n\n    Mat3.prototype.rotatex = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(1, 0, 0, 0, c, s, 0, -s, c);\n    };\n\n    Mat3.prototype.rotatey = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(c, 0, -s, 0, 1, 0, s, 0, c);\n    };\n\n    Mat3.prototype.rotatez = function(angle) {\n      var c, s;\n      s = Math.sin(angle * arc);\n      c = Math.cos(angle * arc);\n      return this.amul(c, s, 0, -s, c, 0, 0, 0, 1);\n    };\n\n    Mat3.prototype.amul = function(b00, b10, b20, b01, b11, b21, b02, b12, b22, b03, b13, b23) {\n      var a, a00, a01, a02, a10, a11, a12, a20, a21, a22;\n      a = this.data;\n      a00 = a[0];\n      a10 = a[1];\n      a20 = a[2];\n      a01 = a[3];\n      a11 = a[4];\n      a21 = a[5];\n      a02 = a[6];\n      a12 = a[7];\n      a22 = a[8];\n      a[0] = a00 * b00 + a01 * b10 + a02 * b20;\n      a[1] = a10 * b00 + a11 * b10 + a12 * b20;\n      a[2] = a20 * b00 + a21 * b10 + a22 * b20;\n      a[3] = a00 * b01 + a01 * b11 + a02 * b21;\n      a[4] = a10 * b01 + a11 * b11 + a12 * b21;\n      a[5] = a20 * b01 + a21 * b11 + a22 * b21;\n      a[6] = a00 * b02 + a01 * b12 + a02 * b22;\n      a[7] = a10 * b02 + a11 * b12 + a12 * b22;\n      a[8] = a20 * b02 + a21 * b12 + a22 * b22;\n      return this;\n    };\n\n    Mat3.prototype.log = function() {\n      var d;\n      d = this.data;\n      return console.log('%f, %f, %f,\\n%f, %f, %f, \\n%f, %f, %f, ', d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8]);\n    };\n\n    return Mat3;\n\n  })();\n\n  window.Mat4 = Mat4 = (function() {\n\n    function Mat4(data) {\n      var _ref;\n      this.data = data;\n      if ((_ref = this.data) == null) {\n        this.data = new Float32Array(16);\n      }\n      this.identity();\n    }\n\n    Mat4.prototype.identity = function() {\n      var d;\n      d = this.data;\n      d[0] = 1;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 0;\n      d[5] = 1;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 0;\n      d[9] = 0;\n      d[10] = 1;\n      d[11] = 0;\n      d[12] = 0;\n      d[13] = 0;\n      d[14] = 0;\n      d[15] = 1;\n      return this;\n    };\n\n    Mat4.prototype.zero = function() {\n      var d;\n      d = this.data;\n      d[0] = 0;\n      d[1] = 0;\n      d[2] = 0;\n      d[3] = 0;\n      d[4] = 0;\n      d[5] = 0;\n      d[6] = 0;\n      d[7] = 0;\n      d[8] = 0;\n      d[9] = 0;\n      d[10] = 0;\n      d[11] = 0;\n      d[12] = 0;\n      d[13] = 0;\n      d[14] = 0;\n      d[15] = 0;\n      return this;\n    };\n\n    Mat4.prototype.copy = function(dest) {\n      var dst, src;\n      src = this.data;\n      dst = dest.data;\n      dst[0] = src[0];\n      dst[1] = src[1];\n      dst[2] = src[2];\n      dst[3] = src[3];\n      dst[4] = src[4];\n      dst[5] = src[5];\n      dst[6] = src[6];\n      dst[7] = src[7];\n      dst[8] = src[8];\n      dst[9] = src[9];\n      dst[10] = src[10];\n      dst[11] = src[11];\n      dst[12] = src[12];\n      dst[13] = src[13];\n      dst[14] = src[14];\n      dst[15] = src[15];\n      return dest;\n    };\n\n    Mat4.prototype.toMat3 = function(dest) {\n      var dst, src;\n      src = this.data;\n      dst = dest.data;\n      dst[0] = src[0];\n      dst[1] = src[1];\n      dst[2] = src[2];\n      dst[3] = src[4];\n      dst[4] = src[5];\n      dst[5] = src[6];\n      dst[6] = src[8];\n      dst[7] = src[9];\n      dst[8] = src[10];\n      return dest;\n    };\n\n    Mat4.prototype.toMat3Rot = function(dest) {\n      var a00, a01, a02, a10, a11, a12, a20, a21, a22, b01, b11, b21, d, dst, id, src;\n      dst = dest.data;\n      src = this.data;\n      a00 = src[0];\n      a01 = src[1];\n      a02 = src[2];\n      a10 = src[4];\n      a11 = src[5];\n      a12 = src[6];\n      a20 = src[8];\n      a21 = src[9];\n      a22 = src[10];\n      b01 = a22 * a11 - a12 * a21;\n      b11 = -a22 * a10 + a12 * a20;\n      b21 = a21 * a10 - a11 * a20;\n      d = a00 * b01 + a01 * b11 + a02 * b21;\n      id = 1 / d;\n      dst[0] = b01 * id;\n      dst[3] = (-a22 * a01 + a02 * a21) * id;\n      dst[6] = (a12 * a01 - a02 * a11) * id;\n      dst[1] = b11 * id;\n      dst[4] = (a22 * a00 - a02 * a20) * id;\n      dst[7] = (-a12 * a00 + a02 * a10) * id;\n      dst[2] = b21 * id;\n      dst[5] = (-a21 * a00 + a01 * a20) * id;\n      dst[8] = (a11 * a00 - a01 * a10) * id;\n      return dest;\n    };\n\n    Mat4.prototype.perspective = function(fov, aspect, near, far) {\n      var bottom, d, left, right, top;\n      this.zero();\n      d = this.data;\n      top = near * Math.tan(fov * Math.PI / 360);\n      right = top * aspect;\n      left = -right;\n      bottom = -top;\n      d[0] = (2 * near) / (right - left);\n      d[5] = (2 * near) / (top - bottom);\n      d[8] = (right + left) / (right - left);\n      d[9] = (top + bottom) / (top - bottom);\n      d[10] = -(far + near) / (far - near);\n      d[11] = -1;\n      d[14] = -(2 * far * near) / (far - near);\n      return this;\n    };\n\n    Mat4.prototype.inversePerspective = function(fov, aspect, near, far) {\n      var bottom, dst, left, right, top;\n      this.zero();\n      dst = this.data;\n      top = near * Math.tan(fov * Math.PI / 360);\n      right = top * aspect;\n      left = -right;\n      bottom = -top;\n      dst[0] = (right - left) / (2 * near);\n      dst[5] = (top - bottom) / (2 * near);\n      dst[11] = -(far - near) / (2 * far * near);\n      dst[12] = (right + left) / (2 * near);\n      dst[13] = (top + bottom) / (2 * near);\n      dst[14] = -1;\n      dst[15] = (far + near) / (2 * far * near);\n      return this;\n    };\n\n    Mat4.prototype.ortho = function(near, far, top, bottom, left, right) {\n      var fn, rl, tb;\n      if (near == null) {\n        near = -1;\n      }\n      if (far == null) {\n        far = 1;\n      }\n      if (top == null) {\n        top = -1;\n      }\n      if (bottom == null) {\n        bottom = 1;\n      }\n      if (left == null) {\n        left = -1;\n      }\n      if (right == null) {\n        right = 1;\n      }\n      rl = right - left;\n      tb = top - bottom;\n      fn = far - near;\n      return this.set(2 / rl, 0, 0, -(left + right) / rl, 0, 2 / tb, 0, -(top + bottom) / tb, 0, 0, -2 / fn, -(far + near) / fn, 0, 0, 0, 1);\n    };\n\n    Mat4.prototype.inverseOrtho = function(near, far, top, bottom, left, right) {\n      var a, b, c, d, e, f, g;\n      if (near == null) {\n        near = -1;\n      }\n      if (far == null) {\n        far = 1;\n      }\n      if (top == null) {\n        top = -1;\n      }\n      if (bottom == null) {\n        bottom = 1;\n      }\n      if (left == null) {\n        left = -1;\n      }\n      if (right == null) {\n        right = 1;\n      }\n      a = (right - left) / 2;\n      b = (right + left) / 2;\n      c = (top - bottom) / 2;\n      d = (top + bottom) / 2;\n      e = (far - near) / -2;\n      f = (near + far) / 2;\n      g = 1;\n      return this.set(a, 0, 0, b, 0, c, 0, d, 0, 0, e, f, 0, 0, 0, g);\n    };\n\n    Mat4.prototype.fromRotationTranslation = function(quat, vec) {\n      var dest, w, wx, wy, wz, x, x2, xx, xy, xz, y, y2, yy, yz, z, z2, zz;\n      x = quat.x;\n      y = quat.y;\n      z = quat.z;\n      w = quat.w;\n      x2 = x + x;\n      y2 = y + y;\n      z2 = z + z;\n      xx = x * x2;\n      xy = x * y2;\n      xz = x * z2;\n      yy = y * y2;\n      yz = y * z2;\n      zz = z * z2;\n      wx = w * x2;\n      wy = w * y2;\n      wz = w * z2;\n      dest = this.data;\n      ' \\ndest[0] = 1 - 2.0 * y * y - 2.0 * y * y\\ndest[1] = 2 * x * y - 2.0 * w * z\\ndest[3] = 2 * x * z + 2.0 * w * y\\n\\ndest[4] = 2 * x * y + 2.0 * w * z\\ndest[5] = 1 - 2.0 * x * x - 2.0 * z * z\\ndest[6] = 2 * y * z - 2.0 * w * x\\n\\ndest[8] = 2 * x * z - 2.0 * w * y\\ndest[9] = 2 * y * z + 2.0 * w * x\\ndest[10] = 1 - 2.0 * x * x - 2.0 * y * y';\n\n      'dest[0] = 1 - 2.0 * y * y - 2.0 * y * y\\ndest[1] = 2 * x * y + 2.0 * w * z\\ndest[2] = 2 * x * z - 2.0 * w * y\\n\\ndest[4] = 2 * x * y - 2.0 * w * z\\ndest[5] = 1 - 2.0 * x * x - 2.0 * z * z\\ndest[6] = 2 * y * z + 2.0 * w * x\\n\\ndest[8] = 2 * x * z + 2.0 * w * y\\ndest[9] = 2 * y * z - 2.0 * w * x\\ndest[10] = 1 - 2.0 * x * x - 2.0 * y * y';\n\n      dest[0] = 1 - (yy + zz);\n      dest[1] = xy + wz;\n      dest[2] = xz - wy;\n      dest[3] = 0;\n      dest[4] = xy - wz;\n      dest[5] = 1 - (xx + zz);\n      dest[6] = yz + wx;\n      dest[7] = 0;\n      dest[8] = xz + wy;\n      dest[9] = yz - wx;\n      dest[10] = 1 - (xx + yy);\n      dest[11] = 0;\n      dest[12] = vec.x;\n      dest[13] = vec.y;\n      dest[14] = vec.z;\n      dest[15] = 1;\n      return this;\n    };\n\n    Mat4.prototype.translateVec3 = function(vec) {\n      return this.translateVal3(vec.x, vec.y, vec.z);\n    };\n\n    Mat4.prototype.translateVal3 = function(x, y, z) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, d;\n      d = this.data;\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[12] = a00 * x + a10 * y + a20 * z + d[12];\n      d[13] = a01 * x + a11 * y + a21 * z + d[13];\n      d[14] = a02 * x + a12 * y + a22 * z + d[14];\n      d[15] = a03 * x + a13 * y + a23 * z + d[15];\n      return this;\n    };\n\n    Mat4.prototype.rotatex = function(angle) {\n      var a10, a11, a12, a13, a20, a21, a22, a23, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[4] = a10 * c + a20 * s;\n      d[5] = a11 * c + a21 * s;\n      d[6] = a12 * c + a22 * s;\n      d[7] = a13 * c + a23 * s;\n      d[8] = a10 * -s + a20 * c;\n      d[9] = a11 * -s + a21 * c;\n      d[10] = a12 * -s + a22 * c;\n      d[11] = a13 * -s + a23 * c;\n      return this;\n    };\n\n    Mat4.prototype.rotatey = function(angle) {\n      var a00, a01, a02, a03, a20, a21, a22, a23, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[0] = a00 * c + a20 * -s;\n      d[1] = a01 * c + a21 * -s;\n      d[2] = a02 * c + a22 * -s;\n      d[3] = a03 * c + a23 * -s;\n      d[8] = a00 * s + a20 * c;\n      d[9] = a01 * s + a21 * c;\n      d[10] = a02 * s + a22 * c;\n      d[11] = a03 * s + a23 * c;\n      return this;\n    };\n\n    Mat4.prototype.rotatez = function(angle) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, c, d, rad, s;\n      d = this.data;\n      rad = tau * (angle / 360);\n      s = Math.sin(rad);\n      c = Math.cos(rad);\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      d[0] = a00 * c + a10 * s;\n      d[1] = a01 * c + a11 * s;\n      d[2] = a02 * c + a12 * s;\n      d[3] = a03 * c + a13 * s;\n      d[4] = a00 * -s + a10 * c;\n      d[5] = a01 * -s + a11 * c;\n      d[6] = a02 * -s + a12 * c;\n      d[7] = a03 * -s + a13 * c;\n      return this;\n    };\n\n    Mat4.prototype.scale = function(scalar) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, d;\n      d = this.data;\n      a00 = d[0];\n      a01 = d[1];\n      a02 = d[2];\n      a03 = d[3];\n      a10 = d[4];\n      a11 = d[5];\n      a12 = d[6];\n      a13 = d[7];\n      a20 = d[8];\n      a21 = d[9];\n      a22 = d[10];\n      a23 = d[11];\n      d[0] = a00 * scalar;\n      d[1] = a01 * scalar;\n      d[2] = a02 * scalar;\n      d[3] = a03 * scalar;\n      d[4] = a10 * scalar;\n      d[5] = a11 * scalar;\n      d[6] = a12 * scalar;\n      d[7] = a13 * scalar;\n      d[8] = a20 * scalar;\n      d[9] = a21 * scalar;\n      d[10] = a22 * scalar;\n      d[11] = a23 * scalar;\n      return this;\n    };\n\n    Mat4.prototype.mulMat4 = function(other, dst) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, a30, a31, a32, a33, b0, b1, b2, b3, dest, mat, mat2;\n      if (dst == null) {\n        dst = this;\n      }\n      dest = dst.data;\n      mat = this.data;\n      mat2 = other.data;\n      a00 = mat[0];\n      a01 = mat[1];\n      a02 = mat[2];\n      a03 = mat[3];\n      a10 = mat[4];\n      a11 = mat[5];\n      a12 = mat[6];\n      a13 = mat[7];\n      a20 = mat[8];\n      a21 = mat[9];\n      a22 = mat[10];\n      a23 = mat[11];\n      a30 = mat[12];\n      a31 = mat[13];\n      a32 = mat[14];\n      a33 = mat[15];\n      b0 = mat2[0];\n      b1 = mat2[1];\n      b2 = mat2[2];\n      b3 = mat2[3];\n      dest[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[4];\n      b1 = mat2[5];\n      b2 = mat2[6];\n      b3 = mat2[7];\n      dest[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[8];\n      b1 = mat2[9];\n      b2 = mat2[10];\n      b3 = mat2[11];\n      dest[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      b0 = mat2[12];\n      b1 = mat2[13];\n      b2 = mat2[14];\n      b3 = mat2[15];\n      dest[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n      dest[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n      dest[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n      dest[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n      return dst;\n    };\n\n    Mat4.prototype.mulVec3 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      return this.mulVal3(vec.x, vec.y, vec.z, dst);\n    };\n\n    Mat4.prototype.mulVal3 = function(x, y, z, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[4] * y + d[8] * z;\n      dst[1] = d[1] * x + d[5] * y + d[9] * z;\n      dst[2] = d[2] * x + d[6] * y + d[10] * z;\n      return dst;\n    };\n\n    Mat4.prototype.mulVec4 = function(vec, dst) {\n      if (dst == null) {\n        dst = vec;\n      }\n      return this.mulVal4(vec.x, vec.y, vec.z, vec.w, dst);\n    };\n\n    Mat4.prototype.mulVal4 = function(x, y, z, w, dst) {\n      var d;\n      dst = dst.data;\n      d = this.data;\n      dst[0] = d[0] * x + d[4] * y + d[8] * z + d[12] * w;\n      dst[1] = d[1] * x + d[5] * y + d[9] * z + d[13] * w;\n      dst[2] = d[2] * x + d[6] * y + d[10] * z + d[14] * w;\n      dst[3] = d[3] * x + d[7] * y + d[11] * z + d[15] * w;\n      return dst;\n    };\n\n    Mat4.prototype.invert = function(dst) {\n      var a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, a30, a31, a32, a33, b00, b01, b02, b03, b04, b05, b06, b07, b08, b09, b10, b11, d, dest, invDet, mat;\n      if (dst == null) {\n        dst = this;\n      }\n      mat = this.data;\n      dest = dst.data;\n      a00 = mat[0];\n      a01 = mat[1];\n      a02 = mat[2];\n      a03 = mat[3];\n      a10 = mat[4];\n      a11 = mat[5];\n      a12 = mat[6];\n      a13 = mat[7];\n      a20 = mat[8];\n      a21 = mat[9];\n      a22 = mat[10];\n      a23 = mat[11];\n      a30 = mat[12];\n      a31 = mat[13];\n      a32 = mat[14];\n      a33 = mat[15];\n      b00 = a00 * a11 - a01 * a10;\n      b01 = a00 * a12 - a02 * a10;\n      b02 = a00 * a13 - a03 * a10;\n      b03 = a01 * a12 - a02 * a11;\n      b04 = a01 * a13 - a03 * a11;\n      b05 = a02 * a13 - a03 * a12;\n      b06 = a20 * a31 - a21 * a30;\n      b07 = a20 * a32 - a22 * a30;\n      b08 = a20 * a33 - a23 * a30;\n      b09 = a21 * a32 - a22 * a31;\n      b10 = a21 * a33 - a23 * a31;\n      b11 = a22 * a33 - a23 * a32;\n      d = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n      if (d === 0) {\n        return;\n      }\n      invDet = 1 / d;\n      dest[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;\n      dest[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;\n      dest[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;\n      dest[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;\n      dest[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;\n      dest[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;\n      dest[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;\n      dest[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;\n      dest[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;\n      dest[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;\n      dest[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;\n      dest[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;\n      dest[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;\n      dest[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;\n      dest[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;\n      dest[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;\n      return dst;\n    };\n\n    Mat4.prototype.set = function(a00, a10, a20, a30, a01, a11, a21, a31, a02, a12, a22, a32, a03, a13, a23, a33) {\n      var d;\n      d = this.data;\n      d[0] = a00;\n      d[4] = a10;\n      d[8] = a20;\n      d[12] = a30;\n      d[1] = a01;\n      d[5] = a11;\n      d[9] = a21;\n      d[13] = a31;\n      d[2] = a02;\n      d[6] = a12;\n      d[10] = a22;\n      d[14] = a32;\n      d[3] = a03;\n      d[7] = a13;\n      d[11] = a23;\n      d[15] = a33;\n      return this;\n    };\n\n    return Mat4;\n\n  })();\n\n}).call(this);\n;\n\n/*! jQuery v1.7.2 jquery.com | jquery.org/license */\n(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f(\"<\"+a+\">\").appendTo(b),e=d.css(\"display\");d.remove();if(e===\"none\"||e===\"\"){ck||(ck=c.createElement(\"iframe\"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?\"<!doctype html>\":\"\")+\"<html><body>\"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,\"display\"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h==\"string\"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k===\"*\")k=l;else if(l!==\"*\"&&l!==k){m=l+\" \"+k,n=e[m]||e[\"* \"+k];if(!n){p=b;for(o in e){j=o.split(\" \");if(j[0]===l||j[0]===\"*\"){p=e[j[1]+\" \"+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error(\"No conversion from \"+m.replace(\" \",\" to \")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]===\"*\")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader(\"content-type\"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+\" \"+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+\"[\"+(typeof e==\"object\"?b:\"\")+\"]\",e,c,d)});else if(!c&&f.type(b)===\"object\")for(var e in b)b_(a+\"[\"+e+\"]\",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l==\"string\"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g[\"*\"]&&(l=bZ(a,c,d,e,\"*\",g));return l}function bY(a){return function(b,c){typeof b!=\"string\"&&(c=b,b=\"*\");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\\+/.test(h),j&&(h=h.substr(1)||\"*\"),i=a[h]=a[h]||[],i[j?\"unshift\":\"push\"](c)}}}function bB(a,b,c){var d=b===\"width\"?a.offsetWidth:a.offsetHeight,e=b===\"width\"?1:0,g=4;if(d>0){if(c!==\"border\")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,\"padding\"+bx[e]))||0),c===\"margin\"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,\"border\"+bx[e]+\"Width\"))||0;return d+\"px\"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,\"padding\"+bx[e]))||0,c!==\"padding\"&&(d+=parseFloat(f.css(a,\"border\"+bx[e]+\"Width\"))||0),c===\"margin\"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+\"px\"}function bo(a){var b=c.createElement(\"div\");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||\"\").toLowerCase();b===\"input\"?bm(a):b!==\"script\"&&typeof a.getElementsByTagName!=\"undefined\"&&f.grep(a.getElementsByTagName(\"input\"),bm)}function bm(a){if(a.type===\"checkbox\"||a.type===\"radio\")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!=\"undefined\"?a.getElementsByTagName(\"*\"):typeof a.querySelectorAll!=\"undefined\"?a.querySelectorAll(\"*\"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c===\"object\"?b.outerHTML=a.outerHTML:c!==\"input\"||a.type!==\"checkbox\"&&a.type!==\"radio\"?c===\"option\"?b.selected=a.defaultSelected:c===\"input\"||c===\"textarea\"?b.defaultValue=a.defaultValue:c===\"script\"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute(\"_submit_attached\"),b.removeAttribute(\"_change_attached\"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,\"table\")?a.getElementsByTagName(\"tbody\")[0]||a.appendChild(a.ownerDocument.createElement(\"tbody\")):a}function U(a){var b=V.split(\"|\"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b==\"string\"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+\"defer\",e=b+\"queue\",g=b+\"mark\",h=f._data(a,d);h&&(c===\"queue\"||!f._data(a,e))&&(c===\"mark\"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b===\"data\"&&f.isEmptyObject(a[b]))continue;if(b!==\"toJSON\")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e=\"data-\"+c.replace(k,\"-$1\").toLowerCase();d=a.getAttribute(e);if(typeof d==\"string\"){try{d=d===\"true\"?!0:d===\"false\"?!1:d===\"null\"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll(\"left\")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\\w\\W]+>)[^>]*$|#([\\w\\-]*)$)/,j=/\\S/,k=/^\\s+/,l=/\\s+$/,m=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>)?$/,n=/^[\\],:{}\\s]*$/,o=/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,q=/(?:^|:|,)(?:\\s*\\[)+/g,r=/(webkit)[ \\/]([\\w.]+)/,s=/(opera)(?:.*version)?[ \\/]([\\w.]+)/,t=/(msie) ([\\w.]+)/,u=/(mozilla)(?:.*? rv:([\\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+\"\").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a===\"body\"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a==\"string\"){a.charAt(0)!==\"<\"||a.charAt(a.length-1)!==\">\"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:\"\",jquery:\"1.7.2\",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b===\"find\"?d.selector=this.selector+(this.selector?\" \":\"\")+c:b&&(d.selector=this.selector+\".\"+b+\"(\"+c+\")\");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),\"slice\",F.call(arguments).join(\",\"))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==\"boolean\"&&(l=i,i=arguments[1]||{},j=2),typeof i!=\"object\"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger(\"ready\").off(\"ready\")}},bindReady:function(){if(!A){A=e.Callbacks(\"once memory\");if(c.readyState===\"complete\")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener(\"DOMContentLoaded\",B,!1),a.addEventListener(\"load\",e.ready,!1);else if(c.attachEvent){c.attachEvent(\"onreadystatechange\",B),a.attachEvent(\"onload\",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)===\"function\"},isArray:Array.isArray||function(a){return e.type(a)===\"array\"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||\"object\"},isPlainObject:function(a){if(!a||e.type(a)!==\"object\"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,\"constructor\")&&!D.call(a.constructor.prototype,\"isPrototypeOf\"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!=\"string\"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,\"@\").replace(p,\"]\").replace(q,\"\")))return(new Function(\"return \"+b))();e.error(\"Invalid JSON: \"+b)},parseXML:function(c){if(typeof c!=\"string\"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,\"text/xml\")):(d=new ActiveXObject(\"Microsoft.XMLDOM\"),d.async=\"false\",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName(\"parsererror\").length)&&e.error(\"Invalid XML: \"+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,\"ms-\").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?\"\":G.call(a)}:function(a){return a==null?\"\":(a+\"\").replace(k,\"\").replace(l,\"\")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d===\"string\"||d===\"function\"||d===\"regexp\"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length==\"number\")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j==\"number\"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c==\"string\"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d==\"object\"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf(\"compatible\")<0&&u.exec(a)||[];return{browser:b[1]||\"\",version:b[2]||\"0\"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each(\"Boolean Number String Function Array Date RegExp Object\".split(\" \"),function(a,b){I[\"[object \"+b+\"]\"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(\" \")&&(k=/^[\\s\\xA0]+/,l=/[\\s\\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener(\"DOMContentLoaded\",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState===\"complete\"&&(c.detachEvent(\"onreadystatechange\",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h===\"array\"?n(g):h===\"function\"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks(\"once memory\"),c=f.Callbacks(\"once memory\"),d=f.Callbacks(\"memory\"),e=\"pending\",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,\"resolve\"],fail:[b,\"reject\"],progress:[c,\"notify\"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+\"With\"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+\"With\"]=g[j].fireWith;i.done(function(){e=\"resolved\"},c.disable,d.lock).fail(function(){e=\"rejected\"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement(\"div\"),q=c.documentElement;p.setAttribute(\"className\",\"t\"),p.innerHTML=\"   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>\",d=p.getElementsByTagName(\"*\"),e=p.getElementsByTagName(\"a\")[0];if(!d||!d.length||!e)return{};g=c.createElement(\"select\"),h=g.appendChild(c.createElement(\"option\")),i=p.getElementsByTagName(\"input\")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName(\"tbody\").length,htmlSerialize:!!p.getElementsByTagName(\"link\").length,style:/top/.test(e.getAttribute(\"style\")),hrefNormalized:e.getAttribute(\"href\")===\"/a\",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value===\"on\",optSelected:h.selected,getSetAttribute:p.className!==\"t\",enctype:!!c.createElement(\"form\").enctype,html5Clone:c.createElement(\"nav\").cloneNode(!0).outerHTML!==\"<:nav></:nav>\",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode===\"CSS1Compat\",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent(\"onclick\",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent(\"onclick\")),i=c.createElement(\"input\"),i.value=\"t\",i.setAttribute(\"type\",\"radio\"),b.radioValue=i.value===\"t\",i.setAttribute(\"checked\",\"checked\"),i.setAttribute(\"name\",\"t\"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m=\"on\"+n,o=m in p,o||(p.setAttribute(m,\"return;\"),o=typeof p[m]==\"function\"),b[n+\"Bubbles\"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName(\"body\")[0];!u||(m=1,t=\"padding:0;margin:0;border:\",r=\"position:absolute;top:0;left:0;width:1px;height:1px;\",s=t+\"0;visibility:hidden;\",n=\"style='\"+r+t+\"5px solid #000;\",q=\"<div \"+n+\"display:block;'><div style='\"+t+\"0;display:block;overflow:hidden;'></div></div>\"+\"<table \"+n+\"' cellpadding='0' cellspacing='0'>\"+\"<tr><td></td></tr></table>\",d=c.createElement(\"div\"),d.style.cssText=s+\"width:0;height:0;position:static;top:0;margin-top:\"+m+\"px\",u.insertBefore(d,u.firstChild),p=c.createElement(\"div\"),d.appendChild(p),p.innerHTML=\"<table><tr><td style='\"+t+\"0;display:none'></td><td>t</td></tr></table>\",k=p.getElementsByTagName(\"td\"),o=k[0].offsetHeight===0,k[0].style.display=\"\",k[1].style.display=\"none\",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML=\"\",l=c.createElement(\"div\"),l.style.width=\"0\",l.style.marginRight=\"0\",p.style.width=\"2px\",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!=\"undefined\"&&(p.innerHTML=\"\",p.style.width=p.style.padding=\"1px\",p.style.border=0,p.style.overflow=\"hidden\",p.style.display=\"inline\",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display=\"block\",p.style.overflow=\"visible\",p.innerHTML=\"<div style='width:5px;'></div>\",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position=\"fixed\",g.style.top=\"20px\",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top=\"\",e.style.overflow=\"hidden\",e.style.position=\"relative\",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop=\"1%\",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!==\"1%\"),typeof d.style.zoom!=\"undefined\"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\\{.*\\}|\\[.*\\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:\"jQuery\"+(f.fn.jquery+Math.random()).replace(/\\D/g,\"\"),noData:{embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c==\"string\",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c===\"events\";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c==\"object\"||typeof c==\"function\")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(\" \")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute(\"classid\")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,\"parsedAttrs\")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf(\"data-\")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,\"parsedAttrs\",!0)}}return m}if(typeof a==\"object\")return this.each(function(){f.data(this,a)});d=a.split(\".\",2),d[1]=d[1]?\".\"+d[1]:\"\",e=d[1]+\"!\";return f.access(this,function(c){if(c===b){m=this.triggerHandler(\"getData\"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler(\"setData\"+e,d),f.data(this,a,c),b.triggerHandler(\"changeData\"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||\"fx\")+\"mark\",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||\"fx\";var d=c+\"mark\",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,\"mark\"))}},queue:function(a,b,c){var d;if(a){b=(b||\"fx\")+\"queue\",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||\"fx\";var c=f.queue(a,b),d=c.shift(),e={};d===\"inprogress\"&&(d=c.shift()),d&&(b===\"fx\"&&c.unshift(\"inprogress\"),f._data(a,b+\".run\",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+\"queue \"+b+\".run\",!0),n(a,b,\"queue\"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!=\"string\"&&(c=a,a=\"fx\",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a===\"fx\"&&b[0]!==\"inprogress\"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||\"fx\";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||\"fx\",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!=\"string\"&&(c=a,a=b),a=a||\"fx\";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+\"defer\",j=a+\"queue\",k=a+\"mark\",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks(\"once memory\"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\\n\\t\\r]/g,p=/\\s+/,q=/\\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=\" \"+e.className+\" \";for(h=0,i=b.length;h<i;h++)~g.indexOf(\" \"+b[h]+\" \")||(g+=b[h]+\" \");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a==\"string\"||a===b){c=(a||\"\").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(\" \"+g.className+\" \").replace(o,\" \");for(i=0,j=c.length;i<j;i++)h=h.replace(\" \"+c[i]+\" \",\" \");g.className=f.trim(h)}else g.className=\"\"}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b==\"boolean\";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c===\"string\"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?\"addClass\":\"removeClass\"](e)}else if(c===\"undefined\"||c===\"boolean\")this.className&&f._data(this,\"__className__\",this.className),this.className=this.className||a===!1?\"\":f._data(this,\"__className__\")||\"\"})},hasClass:function(a){var b=\" \"+a+\" \",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(\" \"+this[c].className+\" \").replace(o,\" \").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h=\"\":typeof h==\"number\"?h+=\"\":f.isArray(h)&&(h=f.map(h,function(a){return a==null?\"\":a+\"\"})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!(\"set\"in c)||c.set(this,h,\"value\")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&\"get\"in c&&(d=c.get(g,\"value\"))!==b)return d;d=g.value;return typeof d==\"string\"?d.replace(q,\"\"):d==null?\"\":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type===\"select-one\";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute(\"disabled\")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,\"optgroup\"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find(\"option\").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute==\"undefined\")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&\"set\"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,\"\"+d);return d}if(h&&\"get\"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,\"\"),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error(\"type property can't be changed\");else if(!f.support.radioValue&&b===\"radio\"&&f.nodeName(a,\"input\")){var c=a.value;a.setAttribute(\"type\",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,\"button\"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,\"button\"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:\"tabIndex\",readonly:\"readOnly\",\"for\":\"htmlFor\",\"class\":\"className\",maxlength:\"maxLength\",cellspacing:\"cellSpacing\",cellpadding:\"cellPadding\",rowspan:\"rowSpan\",colspan:\"colSpan\",usemap:\"useMap\",frameborder:\"frameBorder\",contenteditable:\"contentEditable\"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&\"set\"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&\"get\"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode(\"tabindex\");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!=\"boolean\"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!==\"\":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+\"\"}},f.attrHooks.tabindex.set=w.set,f.each([\"width\",\"height\"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===\"\"){a.setAttribute(b,\"auto\");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===\"\"&&(b=\"false\"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each([\"href\",\"src\",\"width\",\"height\"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=\"\"+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype=\"encoding\"),f.support.checkOn||f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]={get:function(a){return a.getAttribute(\"value\")===null?\"on\":a.value}}}),f.each([\"radio\",\"checkbox\"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\\.]*)?(?:\\.(.+))?$/,B=/(?:^|\\s)hover(\\.\\S+)?\\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\\w*)(?:#([\\w\\-]+))?(?:\\.([\\w\\-]+))?$/,G=function(\na){var b=F.exec(a);b&&(b[1]=(b[1]||\"\").toLowerCase(),b[3]=b[3]&&new RegExp(\"(?:^|\\\\s)\"+b[3]+\"(?:\\\\s|$)\"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c[\"class\"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,\"mouseenter$1 mouseleave$1\")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!=\"undefined\"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(\" \");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||\"\").split(\".\").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(\".\")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent(\"on\"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||\"\")).split(\" \");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp(\"(^|\\\\.)\"+l.split(\".\").sort().join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d===\"**\"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,[\"events\",\"handle\"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf(\"!\")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(\".\")>=0&&(i=h.split(\".\"),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c==\"object\"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join(\".\"),c.namespace_re=c.namespace?new RegExp(\"(^|\\\\.)\"+i.join(\"\\\\.(?:.*\\\\.)?\")+\"(\\\\.|$)\"):null,o=h.indexOf(\":\")<0?\"on\"+h:\"\";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,\"events\")||{})[c.type]&&f._data(m,\"handle\"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!==\"click\"||!f.nodeName(e,\"a\"))&&f.acceptData(e)&&o&&e[h]&&(h!==\"focus\"&&h!==\"blur\"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,\"events\")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!==\"click\")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:\"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:\"focusin\"},blur:{delegateType:\"focusout\"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent(\"on\"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,\"form\"))return!1;f.event.add(this,\"click._submit keypress._submit\",function(a){var c=a.target,d=f.nodeName(c,\"input\")||f.nodeName(c,\"button\")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,\"submit._submit\",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate(\"submit\",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,\"form\"))return!1;f.event.remove(this,\"._submit\")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type===\"checkbox\"||this.type===\"radio\")f.event.add(this,\"propertychange._change\",function(a){a.originalEvent.propertyName===\"checked\"&&(this._just_changed=!0)}),f.event.add(this,\"click._change\",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate(\"change\",this,a,!0))});return!1}f.event.add(this,\"beforeactivate._change\",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,\"change._change\",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate(\"change\",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!==\"radio\"&&b.type!==\"checkbox\")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,\"._change\");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:\"focusin\",blur:\"focusout\"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a==\"object\"){typeof c!=\"string\"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c==\"string\"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+\".\"+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a==\"object\"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c==\"function\")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||\"**\",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,\"**\"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,\"lastToggle\"+a.guid)||0)%d;f._data(this,\"lastToggle\"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!=\"string\"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\\((?:\\([^()]+\\)|[^()]+)+\\)|\\[(?:\\[[^\\[\\]]*\\]|['\"][^'\"]*['\"]|[^\\[\\]'\"]+)+\\]|\\\\.|[^ >+~,(\\[\\\\]+)+|[>+~])(\\s*,\\s*)?((?:.|\\r|\\n)*)/g,d=\"sizcache\"+(Math.random()+\"\").replace(\".\",\"\"),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\\\/g,k=/\\r\\n/g,l=/\\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=\"string\")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(\"\"),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]===\"~\"||w[0]===\"+\")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q=\"\",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)===\"[object Array]\")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!==\"\\\\\"){g[1]=(g[1]||\"\").replace(j,\"\"),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],\"\");break}}}}d||(d=typeof b.getElementsByTagName!=\"undefined\"?b.getElementsByTagName(\"*\"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)===\"\\\\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],\"\");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error(\"Syntax error, unrecognized expression: \"+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e=\"\";if(d){if(d===1||d===9||d===11){if(typeof a.textContent==\"string\")return a.textContent;if(typeof a.innerText==\"string\")return a.innerText.replace(k,\"\");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:[\"ID\",\"NAME\",\"TAG\"],match:{ID:/#((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,CLASS:/\\.((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)/,NAME:/\\[name=['\"]*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)['\"]*\\]/,ATTR:/\\[\\s*((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)\\s*(?:(\\S?=)\\s*(?:(['\"])(.*?)\\3|(#?(?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)*)|)|)\\s*\\]/,TAG:/^((?:[\\w\\u00c0-\\uFFFF\\*\\-]|\\\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\\(\\s*(even|odd|(?:[+\\-]?\\d+|(?:[+\\-]?\\d*)?n\\s*(?:[+\\-]\\s*\\d+)?))\\s*\\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\))?(?=[^\\-]|$)/,PSEUDO:/:((?:[\\w\\u00c0-\\uFFFF\\-]|\\\\.)+)(?:\\((['\"]?)((?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\2\\))?/},leftMatch:{},attrMap:{\"class\":\"className\",\"for\":\"htmlFor\"},attrHandle:{href:function(a){return a.getAttribute(\"href\")},type:function(a){return a.getAttribute(\"type\")}},relative:{\"+\":function(a,b){var c=typeof b==\"string\",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},\">\":function(a,b){var c,d=typeof b==\"string\",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},\"\":function(a,b,c){var d,f=e++,g=x;typeof b==\"string\"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g(\"parentNode\",b,f,a,d,c)},\"~\":function(a,b,c){var d,f=e++,g=x;typeof b==\"string\"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g(\"previousSibling\",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!=\"undefined\"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!=\"undefined\"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute(\"name\")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!=\"undefined\")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=\" \"+a[1].replace(j,\"\")+\" \";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(\" \"+h.className+\" \").replace(/[\\t\\n\\r]/g,\" \").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,\"\")},TAG:function(a,b){return a[1].replace(j,\"\").toLowerCase()},CHILD:function(a){if(a[1]===\"nth\"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\\+|\\s*/g,\"\");var b=/(-?)(\\d*)(?:n([+\\-]?\\d*))?/.exec(a[2]===\"even\"&&\"2n\"||a[2]===\"odd\"&&\"2n+1\"||!/\\D/.test(a[2])&&\"0n+\"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,\"\");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||\"\").replace(j,\"\"),a[2]===\"~=\"&&(a[4]=\" \"+a[4]+\" \");return a},PSEUDO:function(b,c,d,e,f){if(b[1]===\"not\")if((a.exec(b[3])||\"\").length>1||/^\\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!==\"hidden\"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute(\"type\"),c=a.type;return a.nodeName.toLowerCase()===\"input\"&&\"text\"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"radio\"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"checkbox\"===a.type},file:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"file\"===a.type},password:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"password\"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"submit\"===a.type},image:function(a){return a.nodeName.toLowerCase()===\"input\"&&\"image\"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b===\"input\"||b===\"button\")&&\"reset\"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b===\"input\"&&\"button\"===a.type||b===\"button\"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e===\"contains\")return(a.textContent||a.innerText||n([a])||\"\").indexOf(b[3])>=0;if(e===\"not\"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case\"only\":case\"first\":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k===\"first\")return!0;l=a;case\"last\":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case\"nth\":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute(\"id\")===b},TAG:function(a,b){return b===\"*\"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(\" \"+(a.className||a.getAttribute(\"class\"))+\" \").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+\"\",f=b[2],g=b[4];return d==null?f===\"!=\":!f&&m.attr?d!=null:f===\"=\"?e===g:f===\"*=\"?e.indexOf(g)>=0:f===\"~=\"?(\" \"+e+\" \").indexOf(g)>=0:g?f===\"!=\"?e!==g:f===\"^=\"?e.indexOf(g)===0:f===\"$=\"?e.substr(e.length-g.length)===g:f===\"|=\"?e===g||e.substr(0,g.length+1)===g+\"-\":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return\"\\\\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\\[]*\\])(?![^\\(]*\\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\\r|\\n)*?)/.source+o.match[r].source.replace(/\\\\(\\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)===\"[object Array]\")Array.prototype.push.apply(d,a);else if(typeof a.length==\"number\")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement(\"div\"),d=\"script\"+(new Date).getTime(),e=c.documentElement;a.innerHTML=\"<a name='\"+d+\"'/>\",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!=\"undefined\"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=\"undefined\"&&e.getAttributeNode(\"id\").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=\"undefined\"&&a.getAttributeNode(\"id\");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement(\"div\");a.appendChild(c.createComment(\"\")),a.getElementsByTagName(\"*\").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]===\"*\"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML=\"<a href='#'></a>\",a.firstChild&&typeof a.firstChild.getAttribute!=\"undefined\"&&a.firstChild.getAttribute(\"href\")!==\"#\"&&(o.attrHandle.href=function(a){return a.getAttribute(\"href\",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement(\"div\"),d=\"__sizzle__\";b.innerHTML=\"<p class='TEST'></p>\";if(!b.querySelectorAll||b.querySelectorAll(\".TEST\").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\\w+$)|^\\.([\\w\\-]+$)|^#([\\w\\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b===\"body\"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!==\"object\"){var k=e,l=e.getAttribute(\"id\"),n=l||d,p=e.parentNode,q=/^\\s*[+~]/.test(b);l?n=n.replace(/'/g,\"\\\\$&\"):e.setAttribute(\"id\",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll(\"[id='\"+n+\"'] \"+b),f)}catch(r){}finally{l||k.removeAttribute(\"id\")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement(\"div\"),\"div\"),e=!1;try{b.call(c.documentElement,\"[test!='']:sizzle\")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\\=\\s*([^'\"\\]]*)\\s*\\]/g,\"='$1']\");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement(\"div\");a.innerHTML=\"<div class='test e'></div><div class='test'></div>\";if(!!a.getElementsByClassName&&a.getElementsByClassName(\"e\").length!==0){a.lastChild.className=\"e\";if(a.getElementsByClassName(\"e\").length===1)return;o.order.splice(1,0,\"CLASS\"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=\"undefined\"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!==\"HTML\":!1};var y=function(a,b,c){var d,e=[],f=\"\",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,\"\");a=o.relative[a]?a+\"*\":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[\":\"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\\[\\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!=\"string\")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack(\"\",\"find\",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),\"not\",a)},filter:function(a){return this.pushStack(T(this,a,!0),\"filter\",a)},is:function(a){return!!a&&(typeof a==\"string\"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!=\"string\"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,\"closest\",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a==\"string\")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==\"string\"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,\"parentNode\")},parentsUntil:function(a,b,c){return f.dir(a,\"parentNode\",c)},next:function(a){return f.nth(a,2,\"nextSibling\")},prev:function(a){return f.nth(a,2,\"previousSibling\")},nextAll:function(a){return f.dir(a,\"nextSibling\")},prevAll:function(a){return f.dir(a,\"previousSibling\")},nextUntil:function(a,b,c){return f.dir(a,\"nextSibling\",c)},prevUntil:function(a,b,c){return f.dir(a,\"previousSibling\",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,\"iframe\")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d==\"string\"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(\",\"))}}),f.extend({filter:function(a,b,c){c&&(a=\":not(\"+a+\")\");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",W=/ jQuery\\d+=\"(?:\\d+|null)\"/g,X=/^\\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/ig,Z=/<([\\w:]+)/,$=/<tbody/i,_=/<|&#?\\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp(\"<(?:\"+V+\")[\\\\s/>]\",\"i\"),bd=/checked\\s*(?:[^=]|=\\s*.checked.)/i,be=/\\/(java|ecma)script/i,bf=/^\\s*<!(?:\\[CDATA\\[|\\-\\-)/,bg={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],area:[1,\"<map>\",\"</map>\"],_default:[0,\"\",\"\"]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,\"div<div>\",\"</div>\"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,\"body\")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f\n.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,\"before\",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,\"after\",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName(\"*\")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName(\"*\"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,\"\"):null;if(typeof a==\"string\"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||[\"\",\"\"])[1].toLowerCase()]){a=a.replace(Y,\"<$1></$2>\");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName(\"*\")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!=\"string\"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),\"replaceWith\",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j==\"string\"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,\"tr\");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:\"GET\",global:!1,url:b.src,async:!1,dataType:\"script\"}):f.globalEval((b.text||b.textContent||b.innerHTML||\"\").replace(bf,\"/*$0*/\")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j==\"string\"&&j.length<512&&i===c&&j.charAt(0)===\"<\"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test(\"<\"+a.nodeName+\">\")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement==\"undefined\"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l==\"number\"&&(l+=\"\");if(!l)continue;if(typeof l==\"string\")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,\"<$1></$2>\");var m=(Z.exec(l)||[\"\",\"\"])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement(\"div\"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m===\"table\"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===\"<table>\"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],\"tbody\")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)==\"number\")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,\"script\")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName(\"script\"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\\([^)]*\\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\\-+]?(?:\\d*\\.)?\\d+$/i,bt=/^-?(?:\\d*\\.)?\\d+(?!px)[^\\d\\s]+$/i,bu=/^([\\-+])=([\\-+.\\de]+)/,bv=/^margin/,bw={position:\"absolute\",visibility:\"hidden\",display:\"block\"},bx=[\"Top\",\"Right\",\"Bottom\",\"Left\"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,\"opacity\");return c===\"\"?\"1\":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":f.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&\"get\"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h===\"string\"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h=\"number\");if(d==null||h===\"number\"&&isNaN(d))return;h===\"number\"&&!f.cssNumber[i]&&(d+=\"px\");if(!k||!(\"set\"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c===\"cssFloat\"&&(c=\"float\");if(g&&\"get\"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,\"-$1\").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===\"\"&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b===\"fontSize\"?\"1em\":f,f=g.pixelLeft+\"px\",g.left=c,d&&(a.runtimeStyle.left=d));return f===\"\"?\"auto\":f}),by=bz||bA,f.each([\"height\",\"width\"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+\"px\":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||\"\")?parseFloat(RegExp.$1)/100+\"\":b?\"1\":\"\"},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?\"alpha(opacity=\"+b*100+\")\":\"\",g=d&&d.filter||c.filter||\"\";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,\"\"))===\"\"){c.removeAttribute(\"filter\");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+\" \"+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:\"inline-block\"},function(){return b?by(a,\"margin-right\"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,\"display\"))===\"none\"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:\"\",padding:\"\",border:\"Width\"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c==\"string\"?c.split(\" \"):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\\[\\]$/,bE=/\\r?\\n/g,bF=/#.*$/,bG=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\\-storage|.+\\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\\/\\//,bL=/\\?/,bM=/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\\w\\+\\.\\-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=[\"*/\"]+[\"*\"];try{bU=e.href}catch(bX){bU=c.createElement(\"a\"),bU.href=\"\",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!=\"string\"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(\" \");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h=\"GET\";c&&(f.isFunction(c)?(d=c,c=b):typeof c==\"object\"&&(c=f.param(c,f.ajaxSettings.traditional),h=\"POST\"));var i=this;f.ajax({url:a,type:h,dataType:\"html\",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f(\"<div>\").append(c.replace(bM,\"\")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,\"\\r\\n\")}}):{name:b.name,value:c.replace(bE,\"\\r\\n\")}}).get()}}),f.each(\"ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend\".split(\" \"),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each([\"get\",\"post\"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,\"script\")},getJSON:function(a,b,c){return f.get(a,b,c,\"json\")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:\"GET\",contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",processData:!0,async:!0,accepts:{xml:\"application/xml, text/xml\",html:\"text/html\",text:\"text/plain\",json:\"application/json, text/javascript\",\"*\":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\"},converters:{\"* text\":a.String,\"text html\":!0,\"text json\":f.parseJSON,\"text xml\":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||\"\",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader(\"Last-Modified\"))f.lastModified[k]=y;if(z=v.getResponseHeader(\"Etag\"))f.etag[k]=z}if(a===304)w=\"notmodified\",o=!0;else try{r=cb(d,x),w=\"success\",o=!0}catch(A){w=\"parsererror\",u=A}}else{u=w;if(!w||a)w=\"error\",a<0&&(a=0)}v.status=a,v.statusText=\"\"+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger(\"ajax\"+(o?\"Success\":\"Error\"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger(\"ajaxComplete\",[v,d]),--f.active||f.event.trigger(\"ajaxStop\"))}}typeof a==\"object\"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks(\"once memory\"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||\"abort\",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+\"\").replace(bF,\"\").replace(bK,bV[1]+\"//\"),d.dataTypes=f.trim(d.dataType||\"*\").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]===\"http:\"?80:443))==(bV[3]||(bV[1]===\"http:\"?80:443)))),d.data&&d.processData&&typeof d.data!=\"string\"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger(\"ajaxStart\");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?\"&\":\"?\")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,\"$1_=\"+x);d.url=y+(y===d.url?(bL.test(d.url)?\"&\":\"?\")+\"_=\"+x:\"\")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader(\"Content-Type\",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader(\"If-Modified-Since\",f.lastModified[k]),f.etag[k]&&v.setRequestHeader(\"If-None-Match\",f.etag[k])),v.setRequestHeader(\"Accept\",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!==\"*\"?\", \"+bW+\"; q=0.01\":\"\"):d.accepts[\"*\"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,\"No Transport\");else{v.readyState=1,t&&g.trigger(\"ajaxSend\",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort(\"timeout\")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+\"=\"+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join(\"&\").replace(bC,\"+\")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\\=)\\?(&|$)|\\?\\?/i;f.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){return f.expando+\"_\"+cc++}}),f.ajaxPrefilter(\"json jsonp\",function(b,c,d){var e=typeof b.data==\"string\"&&/^application\\/x\\-www\\-form\\-urlencoded/.test(b.contentType);if(b.dataTypes[0]===\"jsonp\"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l=\"$1\"+h+\"$2\";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\\?/.test(j)?\"&\":\"?\")+b.jsonp+\"=\"+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters[\"script json\"]=function(){g||f.error(h+\" was not called\");return g[0]},b.dataTypes[0]=\"json\";return\"script\"}}),f.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/javascript|ecmascript/},converters:{\"text script\":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter(\"script\",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type=\"GET\",a.global=!1)}),f.ajaxTransport(\"script\",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName(\"head\")[0]||c.documentElement;return{send:function(f,g){d=c.createElement(\"script\"),d.async=\"async\",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,\"success\")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&\"withCredentials\"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e[\"X-Requested-With\"]&&(e[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=\"\"}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\\-]=)?([\\d+.\\-]+)([a-z%]*)$/i,co,cp=[[\"height\",\"marginTop\",\"marginBottom\",\"paddingTop\",\"paddingBottom\"],[\"width\",\"marginLeft\",\"marginRight\",\"paddingLeft\",\"paddingRight\"],[\"opacity\"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct(\"show\",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,\"olddisplay\")&&e===\"none\"&&(e=d.style.display=\"\"),(e===\"\"&&f.css(d,\"display\")===\"none\"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,\"olddisplay\",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===\"\"||e===\"none\")d.style.display=f._data(d,\"olddisplay\")||\"\"}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct(\"hide\",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,\"display\"),e!==\"none\"&&!f._data(d,\"olddisplay\")&&f._data(d,\"olddisplay\",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display=\"none\");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a==\"boolean\";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(\":hidden\");f(this)[b?\"show\":\"hide\"]()}):this.animate(ct(\"toggle\",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(\":hidden\").css(\"opacity\",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(\":hidden\"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&\"expand\"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||\"swing\";if(h===\"hide\"&&d||h===\"show\"&&!d)return b.complete.call(this);c&&(g===\"height\"||g===\"width\")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,\"display\")===\"inline\"&&f.css(this,\"float\")===\"none\"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)===\"inline\"?this.style.display=\"inline-block\":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow=\"hidden\");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,\"toggle\"+i)||(h===\"toggle\"?d?\"show\":\"hide\":0),q?(f._data(this,\"toggle\"+i,q===\"show\"?\"hide\":\"show\"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?\"\":\"px\"),p!==\"px\"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]===\"-=\"?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,\"\"));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!=\"string\"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||\"fx\",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(\".run\")===b.length-4&&h(this,g,b);else g[b=a+\".run\"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct(\"show\",1),slideUp:ct(\"hide\",1),slideToggle:ct(\"toggle\",1),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a==\"object\"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration==\"number\"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue=\"fx\";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b===\"auto\"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?\"\":\"px\"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,\"fxshow\"+e.prop)===b&&(e.options.hide?f._data(e.elem,\"fxshow\"+e.prop,e.start):e.options.show&&f._data(e.elem,\"fxshow\"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,\"fxshow\"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop===\"width\"||this.prop===\"height\"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,\"fxshow\"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each([\"\",\"X\",\"Y\"],function(a,b){h.style[\"overflow\"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,\"fxshow\"+b,!0),f.removeData(h,\"toggle\"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,\"opacity\",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf(\"margin\")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;\"getBoundingClientRect\"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position===\"fixed\")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!==\"visible\"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position===\"relative\"||j.position===\"static\")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position===\"fixed\"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,\"marginTop\"))||0,c+=parseFloat(f.css(a,\"marginLeft\"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,\"position\");d===\"static\"&&(a.style.position=\"relative\");var e=f(a),g=e.offset(),h=f.css(a,\"top\"),i=f.css(a,\"left\"),j=(d===\"absolute\"||d===\"fixed\")&&f.inArray(\"auto\",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),\"using\"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,\"marginTop\"))||0,c.left-=parseFloat(f.css(a,\"marginLeft\"))||0,d.top+=parseFloat(f.css(b[0],\"borderTopWidth\"))||0,d.left+=parseFloat(f.css(b[0],\"borderLeftWidth\"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,\"position\")===\"static\")a=a.offsetParent;return a})}}),f.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:\"height\",Width:\"width\"},function(a,c){var d=\"client\"+a,e=\"scroll\"+a,g=\"offset\"+a;f.fn[\"inner\"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,\"padding\")):this[c]():null},f.fn[\"outer\"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?\"margin\":\"border\")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define==\"function\"&&define.amd&&define.amd.jQuery&&define(\"jquery\",[],function(){return f})})(window);;\n\n    loader.define('/application.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Antialias, CompositingControl, Cube, DeferredModel, DeferredShadowMap, Illumination, Lighting, LowresModel, Model, PictureSettings, Quad, Rendernode, SHConstants, SSAO, Sun, Windows, camera, loading, makeStat, schedule, _ref,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nschedule = require('schedule');\n\nloading = require('loading');\n\ncamera = require('camera');\n\nQuad = require('/webgl/quad');\n\nCube = require('/webgl/cube');\n\nAntialias = require('antialias');\n\n_ref = require('model'), LowresModel = _ref.LowresModel, Model = _ref.Model;\n\nIllumination = require('illumination');\n\nRendernode = require('/rendernode');\n\nWindows = require('/windows');\n\nDeferredShadowMap = require('/depth').DeferredShadowMap;\n\nSun = require('sun');\n\nDeferredModel = require('deferred_model');\n\nSSAO = require('ssao');\n\nCompositingControl = (function() {\n\n  function CompositingControl(gui) {\n    var folder;\n    gui.remember(this);\n    this.draw_probes = false;\n    this.gi = 1;\n    this.di = 1;\n    this.ao = 0.8;\n    folder = gui.addFolder('Compositing');\n    folder.add(this, 'draw_probes').name('Draw Probes');\n    folder.add(this, 'gi', 0.0, 2.0).name('Glob. Illum.');\n    folder.add(this, 'di', 0.0, 2.0).name('Direct. Illum.');\n    folder.add(this, 'ao', 0.0, 1.0).name('SSAO');\n  }\n\n  return CompositingControl;\n\n})();\n\nLighting = (function(_super) {\n\n  __extends(Lighting, _super);\n\n  function Lighting(gui) {\n    this.update = __bind(this.update, this);\n\n    this.bouncesChanged = __bind(this.bouncesChanged, this);\n\n    this.computeRadiance = __bind(this.computeRadiance, this);\n\n    var folder;\n    gui.remember(this);\n    Lighting.__super__.constructor.call(this);\n    this.sunRadiance = 1.0;\n    this.skyRadiance = 1.0;\n    this.giGain = 1.0;\n    this.bounces = 3;\n    this.sunColor = [255, 255, 255];\n    this.skyColor = [0x07, 0xcb, 0xf5];\n    this.sun_radiance = [0, 0, 0];\n    this.sky_radiance = [0, 0, 0];\n    folder = gui.addFolder('Lighting');\n    folder.addColor(this, 'sunColor').name('Sun Color').onChange(this.computeRadiance);\n    folder.add(this, 'sunRadiance', 0.0, 20.0).name('Sun Radiance').onChange(this.computeRadiance);\n    folder.addColor(this, 'skyColor').name('Sky Color').onChange(this.computeRadiance);\n    folder.add(this, 'skyRadiance', 0.0, 20.0).name('Sky Radiance').onChange(this.computeRadiance);\n    folder.add(this, 'giGain', 0.0, 20.0).name('GI-gain').onChange(this.update);\n    folder.add(this, 'bounces', 1.0, 10.0).step(1).name('Bounces').onChange(this.bouncesChanged);\n    this.computeRadiance();\n    this.lastbounces = this.bounces;\n  }\n\n  Lighting.prototype.computeRadiance = function() {\n    this.sun_radiance[0] = this.sunRadiance * (this.sunColor[0] / 255.0);\n    this.sun_radiance[1] = this.sunRadiance * (this.sunColor[1] / 255.0);\n    this.sun_radiance[2] = this.sunRadiance * (this.sunColor[2] / 255.0);\n    this.sky_radiance[0] = this.skyRadiance * (this.skyColor[0] / 255.0);\n    this.sky_radiance[1] = this.skyRadiance * (this.skyColor[1] / 255.0);\n    this.sky_radiance[2] = this.skyRadiance * (this.skyColor[2] / 255.0);\n    return this.update();\n  };\n\n  Lighting.prototype.bouncesChanged = function() {\n    if (this.bounces !== this.lastBounces) {\n      this.lastBounces = this.bounces;\n      return this.update();\n    }\n  };\n\n  Lighting.prototype.update = function() {\n    return this.trigger('change');\n  };\n\n  return Lighting;\n\n})(require('events'));\n\nPictureSettings = (function() {\n\n  function PictureSettings(gui) {\n    var folder;\n    gui.remember(this);\n    this.inputGamma = 1.8;\n    this.outputGamma = 1.8;\n    this.brightness = 1.0;\n    this.saturation = 1.0;\n    folder = gui.addFolder('Picture');\n    folder.add(this, 'inputGamma', 0.25, 3.0).name('Input Gamma');\n    folder.add(this, 'outputGamma', 0.25, 3.0).name('Output Gamma');\n    folder.add(this, 'brightness', 0.0, 10.0).name('Exposure');\n    folder.add(this, 'saturation', 0.0, 4.0).name('Saturation');\n  }\n\n  return PictureSettings;\n\n})();\n\nSHConstants = (function() {\n\n  function SHConstants(app, gui) {\n    var folder;\n    this.app = app;\n    this.change = __bind(this.change, this);\n\n    gui.remember(this);\n    this.c1 = 0.43;\n    this.c2 = 0.66;\n    this.band3 = 1.0;\n    this.c3 = 0.9;\n    this.c4 = 0.34;\n    this.c5 = 0.43;\n    this.data = new Float32Array(5);\n    folder = gui.addFolder('Harmonics');\n    folder.add(this, 'c1', 0.0, 4.0).name('L0').onChange(this.change);\n    folder.add(this, 'c2', 0.0, 4.0).name('L1').onChange(this.change);\n    folder.add(this, 'band3', 0.0, 4.0).name('L2').onChange(this.change);\n    folder.add(this, 'c3', 0.0, 4.0).name('L2m2/L2m1/L21').onChange(this.change);\n    folder.add(this, 'c4', 0.0, 4.0).name('L20').onChange(this.change);\n    folder.add(this, 'c5', 0.0, 4.0).name('L22').onChange(this.change);\n    this.updateData();\n  }\n\n  SHConstants.prototype.updateData = function() {\n    this.data[0] = this.c1;\n    this.data[1] = this.c2;\n    this.data[2] = this.band3 * this.c3;\n    this.data[3] = this.band3 * this.c4;\n    return this.data[4] = this.band3 * this.c5;\n  };\n\n  SHConstants.prototype.change = function() {\n    this.updateData();\n    return this.app.lightChange();\n  };\n\n  return SHConstants;\n\n})();\n\nmakeStat = function(mode, offset) {\n  var node, stats;\n  stats = new Stats();\n  stats.setMode(mode);\n  node = $(stats.domElement);\n  node.css({\n    position: 'absolute',\n    left: offset,\n    top: 0\n  }).appendTo('body').hide();\n  stats.hide = function() {\n    return node.clearQueue().fadeOut();\n  };\n  stats.show = function() {\n    return node.clearQueue().fadeIn();\n  };\n  return stats;\n};\n\nexports.Application = (function() {\n\n  function _Class(canvas) {\n    var floatExt, folder, gui, resmap,\n      _this = this;\n    this.canvas = canvas;\n    this.update = __bind(this.update, this);\n\n    this.resize = __bind(this.resize, this);\n\n    this.lightChange = __bind(this.lightChange, this);\n\n    this.sunChanged = __bind(this.sunChanged, this);\n\n    $('<div id=\"controls\"></div>').css('margin', 10).appendTo('#ui');\n    Rendernode.stateDefaults(gl);\n    gui = this.gui = new dat.GUI({\n      load: get('presets/new.json')\n    });\n    gui.remember(this);\n    this.gui_width = gui.width = 370;\n    this.gui.closed = false;\n    this.fps = makeStat(0, 0);\n    this.rtime = makeStat(1, 80);\n    this.gui_closed = gui.closed;\n    this.resolution = 0.5;\n    this.resolution_label = '1:2 default';\n    resmap = {\n      '2:1 very slow!': 2,\n      '1:1 slow': 1,\n      '1:2 default': 0.5,\n      '1:4 ugly': 0.25,\n      '1:8 worse': 0.125\n    };\n    folder = gui.addFolder('Performance');\n    $('<li>WASD=move, space=overview, cursor keys=navigate</li>').appendTo(folder.__ul);\n    folder.add(this, 'resolution_label', ['2:1 very slow!', '1:1 slow', '1:2 default', '1:4 ugly', '1:8 worse']).name('Resolution').onChange(function() {\n      _this.resolution = resmap[_this.resolution_label];\n      return _this.resizeBuffers();\n    });\n    this.resolution = resmap[this.resolution_label];\n    this.show_fps = false;\n    folder.add(this, 'show_fps').name('FPS').onChange(function() {\n      if (_this.show_fps) {\n        _this.fps.show();\n        return _this.rtime.show();\n      } else {\n        _this.fps.hide();\n        return _this.rtime.hide();\n      }\n    });\n    if (this.show_fps) {\n      this.fps.show();\n      this.rtime.show();\n    } else {\n      this.fps.hide();\n      this.rtime.hide();\n    }\n    this.picture = new PictureSettings(gui);\n    this.sun = new Sun(gui).on('change', this.sunChanged);\n    this.compositing_control = new CompositingControl(gui);\n    this.lighting = new Lighting(gui).on('change', this.lightChange);\n    this.shconst = new SHConstants(this, gui);\n    loading.hide();\n    this.near = 0.1;\n    this.far = 42;\n    this.camera = new camera.FlyCam({\n      gui: gui,\n      near: this.near,\n      far: this.far,\n      x: -10,\n      y: 7,\n      z: -1.5,\n      o: 100,\n      p: 20\n    });\n    this.sponza = new Model(gl);\n    this.lowres = new LowresModel(gl);\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.view_normaldepth = new Rendernode(gl, {\n      program: get('normaldepth.shader'),\n      drawable: this.sponza,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      cullFace: 'BACK',\n      type: floatExt.type,\n      filter: 'nearest',\n      hdrClear: true\n    });\n    this.ssao = new SSAO(gl, this.view_normaldepth);\n    this.direct_light = new DeferredShadowMap(gl, {\n      drawable: this.sponza,\n      depthWidth: 512,\n      depthHeight: 512,\n      eyeNormaldepth: this.view_normaldepth,\n      light: this.sun,\n      camera: this.camera,\n      blurred: true\n    });\n    this.illumination = new Illumination(gl, this.sun, this.lighting, this.lowres, this.sponza, this.view_normaldepth, this.sun.orientation, this.sun.elevation, this.shconst);\n    this.albedo = new Rendernode(gl, {\n      program: get('albedo.shader'),\n      drawable: this.sponza,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true\n    });\n    this.global_illumination = new Rendernode(gl, {\n      program: get('global_illumination.shader'),\n      drawable: new DeferredModel(gl, this.illumination.probes),\n      cullFace: 'FRONT',\n      blend: 'additive',\n      type: floatExt.type,\n      depthBuffer: this.view_normaldepth.depth,\n      depthWrite: false,\n      depthTest: 'GEQUAL'\n    });\n    this.composit = new Rendernode(gl, {\n      program: get('composit.shader'),\n      drawable: quad\n    });\n    this.antialias = new Antialias(gl, gui, this.composit);\n    this.windows = new Windows(gl, gui, [\n      {\n        label: 'Scene depth from sun',\n        affine: [1, 0],\n        gamma: false,\n        tex: this.direct_light.depth.output\n      }, {\n        label: 'Scene normal/depth',\n        affine: [0.5, 0.5],\n        gamma: false,\n        tex: this.view_normaldepth\n      }, {\n        label: 'Scene depth moments',\n        gamma: false,\n        tex: this.ssao.blur.output\n      }, {\n        label: 'Direct Illumination Lightmap',\n        tex: this.illumination.direct_light.output\n      }, {\n        label: 'Global Illumination Lightmap',\n        diva: true,\n        tex: this.illumination.bounce\n      }, {\n        label: 'Lightmap Dictionary',\n        tex: this.illumination.texmap\n      }, {\n        label: 'Albedo Probe Values',\n        tex: this.illumination.diffusemap\n      }, {\n        label: 'Light Probes',\n        tex: this.illumination.lightprobes\n      }, {\n        label: 'Spherical Harmonics Coefficients',\n        tex: this.illumination.coefficients\n      }, {\n        label: 'Albedo',\n        tex: this.albedo\n      }, {\n        label: 'SSAO',\n        gamma: false,\n        tex: this.ssao.output\n      }, {\n        label: 'Direct Illumination',\n        tex: this.direct_light.output\n      }, {\n        label: 'Global Illumination',\n        diva: true,\n        tex: this.global_illumination\n      }, {\n        label: 'Composited',\n        gamma: false,\n        tex: this.composit\n      }, {\n        label: 'Antialiased',\n        gamma: false,\n        tex: this.antialias.node\n      }\n    ]);\n    this.target_width = this.canvas.width();\n    this.current_width = this.target_width;\n    $(window).resize(this.resize);\n    this.resize();\n    schedule.run(this.update);\n    this.canvas.fadeIn(2000);\n    $('div.dg > ul').css('margin-top', 0);\n  }\n\n  _Class.prototype.sunChanged = function() {\n    this.direct_light.updateDepth();\n    this.illumination.updateDirectLight();\n    return this.lightChange();\n  };\n\n  _Class.prototype.lightChange = function() {\n    return this.illumination.update();\n  };\n\n  _Class.prototype.resizeBuffers = function(width, height) {\n    var h, w;\n    w = this.width * this.resolution;\n    h = this.height * this.resolution;\n    this.view_normaldepth.resize(w, h);\n    this.albedo.resize(w, h);\n    this.global_illumination.resize(w, h);\n    this.direct_light.resize(w, h);\n    this.composit.resize(w, h);\n    this.antialias.resize(w, h);\n    this.illumination.debug.resize(w, h);\n    return this.ssao.resize(w, h);\n  };\n\n  _Class.prototype.resize = function() {\n    this.width = this.canvas.width();\n    this.height = this.canvas.height();\n    this.camera.aspect(this.width, this.height);\n    this.canvas[0].width = this.width;\n    this.canvas[0].height = this.height;\n    this.resizeBuffers(this.width, this.height);\n    return this.resizeWindows();\n  };\n\n  _Class.prototype.update = function() {\n    this.fps.end();\n    this.fps.begin();\n    this.rtime.begin();\n    this.step();\n    this.draw();\n    return this.rtime.end();\n  };\n\n  _Class.prototype.resizeWindows = function() {\n    return this.windows.node.viewport(0, 0, this.current_width, this.height);\n  };\n\n  _Class.prototype.step = function() {\n    var dw, gui_closed, gui_width;\n    gui_closed = this.gui.closed;\n    if (gui_closed) {\n      this.target_width = this.width;\n    } else {\n      gui_width = this.gui.width;\n      this.target_width = this.width - (gui_width + 10);\n    }\n    dw = this.target_width - this.current_width;\n    this.current_width = this.current_width + dw * 0.1;\n    dw = Math.abs(this.target_width - this.current_width);\n    if (dw > 1) {\n      this.resizeWindows();\n    } else if (dw <= 1 && dw > 0) {\n      this.current_width = this.target_width;\n      this.resizeWindows();\n    }\n    return this.camera.update();\n  };\n\n  _Class.prototype.draw = function() {\n    var probe_factor;\n    this.view_normaldepth.clear(0, 0, 0, 100).start().clearDepth().mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat3('view_rot', this.camera.rot).drawModel('bumpmap').end();\n    this.ssao.update();\n    this.albedo.start().f('gamma', this.picture.inputGamma).mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat3('view_rot', this.camera.rot).clearBoth(0, 0, 0, 0).drawModel('diffuse_texture').end();\n    this.global_illumination.start().f('gi_gain', this.lighting.giGain).fv('shconst', this.shconst.data).sampler('normaldepth', this.view_normaldepth).mat4('proj', this.camera.proj).mat4('view', this.camera.view).mat4('inv_view', this.camera.inv_view).sampler('coefficients', this.illumination.coefficients).val2('coefficients_size', this.illumination.coefficients.width, this.illumination.coefficients.height).clear().draw().end();\n    this.direct_light.updateShadow();\n    if (this.compositing_control.draw_probes) {\n      probe_factor = 1;\n      this.illumination.drawDebug(this.camera, this.view_normaldepth);\n    } else {\n      probe_factor = 0;\n    }\n    this.composit.start().clear().f('gamma', this.picture.outputGamma).f('brightness', this.picture.brightness).f('saturation', this.picture.saturation).vec3('sun_radiance', this.lighting.sun_radiance).vec3('sky_radiance', this.lighting.sky_radiance).f('probe_factor', probe_factor).f('gi_factor', this.compositing_control.gi).f('di_factor', this.compositing_control.di).f('ao_factor', this.compositing_control.ao).vec3('sky_color', this.lighting.skyColor).sampler('debug', this.illumination.debug).sampler('albedo', this.albedo).sampler('global', this.global_illumination).sampler('direct', this.direct_light.output).sampler('ssao', this.ssao.output).draw().end();\n    this.antialias.apply();\n    return this.windows.draw(this.picture.outputGamma);\n  };\n\n  return _Class;\n\n})();\n});\n    \n    loader.define('/deferred_model.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar DeferredModel, Sphere,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nSphere = require('/webgl/sphere');\n\nreturn DeferredModel = (function(_super) {\n\n  __extends(DeferredModel, _super);\n\n  DeferredModel.prototype.attribs = ['position', 'lightprobe', 'center'];\n\n  DeferredModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 7\n    }, {\n      name: 'lightprobe',\n      size: 4,\n      offset: 3,\n      stride: 7\n    }\n  ];\n\n  function DeferredModel(gl, probes) {\n    var buffer, i, probe, px, py, pz, template, vi, x, y, z, _i, _j, _len, _ref;\n    this.gl = gl;\n    DeferredModel.__super__.constructor.call(this);\n    template = Sphere.makeVertices(5.1, 2);\n    buffer = [];\n    for (i = _i = 0, _len = probes.length; _i < _len; i = ++_i) {\n      probe = probes[i];\n      px = probe.x;\n      py = probe.y;\n      pz = probe.z;\n      for (vi = _j = 0, _ref = template.length; _j < _ref; vi = _j += 3) {\n        x = template[vi];\n        y = template[vi + 1];\n        z = template[vi + 2];\n        buffer.push(x, y, z, px, py, pz, i);\n      }\n    }\n    this.size = buffer.length / 7;\n    this.uploadList(buffer);\n  }\n\n  return DeferredModel;\n\n})(require('webgl/drawable'));\n});\n    \n    loader.define('/main.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Quad, Shader, audio, disableSelect, enableSelect, errorContainer, load_hooks, loading;\n\naudio = require('audio');\n\nloading = require('loading');\n\nShader = require('webgl/shader');\n\nQuad = require('webgl/quad');\n\nrequire('webgl-nuke-vendor-prefix');\n\nrequire('webgl-texture-float-extension-shims');\n\nload_hooks = {\n  '\\.jpg$|\\.jpeg$|\\.gif$|\\.png': function(name, buffer, callback) {\n    var ext, image, mime;\n    ext = name.split('.').pop();\n    switch (ext) {\n      case 'png':\n        mime = 'image/png';\n        break;\n      case 'gif':\n        mime = 'image/gif';\n        break;\n      case 'jpg':\n      case 'jpeg':\n        mime = 'image/jpeg';\n    }\n    image = new Image();\n    image.src = getURL(buffer, mime);\n    return image.onload = function() {\n      return callback(image);\n    };\n  },\n  '\\.mpg$|\\.ogg$|\\.wav$': function(name, buffer, callback) {\n    return audio.decode(buffer, function(result) {\n      return callback(result);\n    });\n  }\n};\n\nerrorContainer = function(title) {\n  canvas.remove();\n  $('#ui').empty();\n  return $('<div></div>').css({\n    position: 'absolute',\n    width: 300,\n    left: '50%',\n    top: 50,\n    marginLeft: -100\n  }).append($('<h1></h1>').text(title)).appendTo('#ui');\n};\n\ndisableSelect = function() {\n  $('*').each(function() {\n    $(this).attr('unselectable', 'on').css({\n      '-moz-user-select': 'none',\n      '-webkit-user-select': 'none',\n      'user-select': 'none',\n      '-ms-user-select': 'none'\n    });\n    return this.onselectstart = function() {\n      return false;\n    };\n  });\n  return document.oncontextmenu = function() {\n    return false;\n  };\n};\n\nenableSelect = function() {\n  $('*').each(function() {\n    $(this).removeAttr('unselectable').css({\n      '-moz-user-select': 'text',\n      '-webkit-user-select': 'text',\n      'user-select': 'text',\n      '-ms-user-select': 'text'\n    });\n    return this.onselectstart = void 0;\n  });\n  return document.oncontextmenu = void 0;\n};\n\nexports.main = function() {\n  var Application, application, container, floatExt, stddev;\n  disableSelect();\n  window.canvas = $('canvas');\n  window.onerror = function(error) {\n    if (error.search(Shader.error) > 0) {\n      return true;\n    }\n  };\n  try {\n    window.gl = canvas[0].getContext('experimental-webgl');\n    if (!window.gl) {\n      window.gl = canvas[0].getContext('webgl');\n    }\n  } catch (_error) {}\n  if (window.gl) {\n    window.quad = new Quad(window.gl);\n    stddev = gl.getExtension('OES_standard_derivatives');\n    if (!stddev) {\n      return errorContainer('Missing Extension: Standard Derivatives').append('<p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/\">Standard Derivatives extension</a> which you do not have, sorry.</p>');\n    }\n    floatExt = gl.getFloatExtension({\n      require: ['renderable'],\n      prefer: ['filterable', 'half'],\n      throws: false\n    });\n    if (!floatExt) {\n      return errorContainer('Missing Extension: Floating Point Textures').append('<p>This application requires the WebGL <a href=\"http://www.khronos.org/registry/webgl/extensions/OES_texture_float/\">Floating Point Textures extension</a> which you do not have, sorry.</p>');\n    }\n    Application = require('application').Application;\n    application = null;\n    loading.show('Loading ...');\n    return loader.hooks(load_hooks).mount({\n      url: 'assets.pack',\n      loaded: function(files, fs) {\n        var container, name, value;\n        for (name in files) {\n          value = files[name];\n          if (name.match('\\.shaderlib$')) {\n            fs[name] = Shader.splitLines(name, value);\n          }\n        }\n        try {\n          for (name in files) {\n            value = files[name];\n            if (name.match('\\.shader$')) {\n              fs[name] = new Shader(gl, name, value);\n            }\n          }\n          return application = new Application(window.canvas, window.gl);\n        } catch (error) {\n          if (error === 'ShaderError') {\n            enableSelect();\n            container = errorContainer('Shader Error').append('<p>\\n    An error occured when compiling a shader, you can <a href=\"mailto:pyalot@gmail.com\">paste me the error</a>.\\n</p>');\n            container.css({\n              width: 600,\n              marginLeft: -300\n            });\n            return $('<pre></pre>').text(Shader.lastError).css('overflow', 'auto').appendTo(container);\n          } else {\n            throw error;\n          }\n        }\n      },\n      progress: loading.progress\n    });\n  } else {\n    container = errorContainer('You dont have WebGL');\n    if ($.browser.msie) {\n      container.append('<p>\\n    You have Internet Explorer, please install\\n    <a href=\"https://www.google.com/intl/en/chrome/browser/\">Google Chrome</a> or\\n    <a href=\"http://www.mozilla.org/en-US/firefox/new/\">Firefox</a>\\n</p>');\n    } else if ($.browser.webkit) {\n      container.append('<p>\\n    If you use OSX Safari, please <a href=\"http://www.ikriz.nl/2011/08/23/enable-webgl-in-safari\">enable WebGL manually</a>.\\n    If you use iOS Safari, you cannot use WebGL.\\n    If you use Android, please try <a href=\"http://www.mozilla.org/en-US/mobile/\">Firefox Mobile</a> or\\n    <a href=\"https://play.google.com/store/apps/details?id=com.opera.browser&hl=en\">Opera Mobile</a>\\n</p>');\n    }\n    return container.append('<p>\\n    Please consult the <a href=\"http://support.google.com/chrome/bin/answer.py?hl=en&answer=1220892\">support pages</a>\\n    on how to get WebGL for your machine.\\n</p>');\n  }\n};\n});\n    \n    loader.define('/sun.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Sun,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Sun = (function(_super) {\n\n  __extends(Sun, _super);\n\n  function Sun(gui, orientation, elevation) {\n    var folder;\n    this.orientation = orientation != null ? orientation : 104;\n    this.elevation = elevation != null ? elevation : 60;\n    this.update = __bind(this.update, this);\n\n    gui.remember(this);\n    Sun.__super__.constructor.call(this);\n    folder = gui.addFolder('Sun');\n    folder.add(this, 'orientation', 0, 360).onChange(this.update);\n    folder.add(this, 'elevation', 0, 90).onChange(this.update);\n    this.near = -1;\n    this.far = 41;\n    this.proj = new Mat4().ortho(this.near, this.far, 21, -21, -21, 21);\n    this.view = new Mat4();\n    this.rot = new Mat3();\n    this.update();\n  }\n\n  Sun.prototype.update = function() {\n    this.view.identity().translateVal3(0, 0, -21).rotatex(this.elevation).rotatey(this.orientation).translateVal3(0, -7.5, 0).toMat3(this.rot.identity());\n    this.trigger('change');\n    return this;\n  };\n\n  return Sun;\n\n})(require('events'));\n});\n    \n    loader.define('/dist3d.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar cross, dot, length, sadd, slength, smul, vadd, vsub;\n\nvsub = function(p1, p2) {\n  return [p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]];\n};\n\nvadd = function(p1, p2) {\n  return [p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]];\n};\n\nsadd = function(s, p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return [x + s, y + s, z + s];\n};\n\nslength = function(p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return x * x + y * y + z * z;\n};\n\nlength = function(p) {\n  return Math.sqrt(slength(p));\n};\n\ndot = function(p1, p2) {\n  var x1, x2, y1, y2, z1, z2;\n  x1 = p1[0];\n  y1 = p1[1];\n  z1 = p1[2];\n  x2 = p2[0];\n  y2 = p2[1];\n  z2 = p2[2];\n  return x1 * x2 + y1 * y2 + z1 * z2;\n};\n\nsmul = function(s, p) {\n  var x, y, z;\n  x = p[0];\n  y = p[1];\n  z = p[2];\n  return [x * s, y * s, z * s];\n};\n\ncross = function(p1, p2) {\n  var x1, x2, y1, y2, z1, z2;\n  x1 = p1[0];\n  y1 = p1[1];\n  z1 = p1[2];\n  x2 = p2[0];\n  y2 = p2[1];\n  z2 = p2[2];\n  return [y1 * z2 - z1 * y2, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2];\n};\n\nexports.closestPointTriangle = function(p, a, b, c) {\n  var ab, ac, bc, n, sdenom, snom, tdenom, tnom, u, udenom, unom, v, va, vb, vc, w;\n  ab = vsub(b, a);\n  ac = vsub(c, a);\n  bc = vsub(c, b);\n  snom = dot(vsub(p, a), ab);\n  sdenom = dot(vsub(p, b), vsub(a, b));\n  tnom = dot(vsub(p, a), ac);\n  tdenom = dot(vsub(p, c), vsub(a, c));\n  if (snom <= 0 && tnom <= 0) {\n    return a;\n  }\n  unom = dot(vsub(p, b), bc);\n  udenom = dot(vsub(p, c), vsub(b, c));\n  if (sdenom <= 0 && unom <= 0) {\n    return b;\n  }\n  if (tdenom <= 0 && udenom <= 0) {\n    return c;\n  }\n  n = cross(vsub(b, a), vsub(c, a));\n  vc = dot(n, cross(vsub(a, p), vsub(b, p)));\n  if (vc <= 0 && snom >= 0 && sdenom >= 0) {\n    return vadd(a, smul(snom / (snom + sdenom), ab));\n  }\n  va = dot(n, cross(vsub(b, p), vsub(c, p)));\n  if (va <= 0 && unom >= 0 && udenom >= 0) {\n    return vadd(b, smul(unom / (unom + udenom), bc));\n  }\n  vb = dot(n, cross(vsub(c, p), vsub(a, p)));\n  if (vb <= 0 && tnom > 0 && tdenom >= 0) {\n    return vadd(a, smul(tnom / (tnom + tdenom), ac));\n  }\n  u = va / (va + vb + vc);\n  v = vb / (va + vb + vc);\n  w = 1 - u - v;\n  return vadd(smul(u, a), vadd(smul(v, b), smul(w, c)));\n};\n\nexports.pointTriangleDist = function(p, v0, v1, v2) {\n  var cx, cy, cz, dx, dy, dz, px, py, pz, _ref;\n  _ref = exports.closestPointTriangle(p, v0, v1, v2), cx = _ref[0], cy = _ref[1], cz = _ref[2];\n  px = p[0], py = p[1], pz = p[2];\n  dx = cx - px;\n  dy = cy - py;\n  dz = cz - pz;\n  return Math.sqrt(dx * dx + dy * dy + dz * dz);\n};\n});\n    \n    loader.define('/windows/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Quad, Rendernode, Window, Windows, keys,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nQuad = require('/webgl/quad');\n\nRendernode = require('/rendernode');\n\nkeys = require('/keys');\n\nWindow = (function() {\n\n  function Window(index, texture, node, x, y) {\n    this.index = index;\n    this.texture = texture;\n    this.node = node;\n    this.x = x;\n    this.y = y;\n    this.label = this.texture.label;\n    if (this.texture.diva) {\n      this.diva = 1;\n    } else {\n      this.diva = 0;\n    }\n    if (this.texture.gamma === false) {\n      this.gamma = 0;\n    } else {\n      this.gamma = 1;\n    }\n    if (this.texture.affine) {\n      this.mul = this.texture.affine[0];\n      this.add = this.texture.affine[1];\n    } else {\n      this.mul = 1;\n      this.add = 0;\n    }\n  }\n\n  Window.prototype.draw = function(xscale, yscale, one2one, cx, cy, active) {\n    var h, height, max, s, w, width;\n    width = this.texture.tex.width;\n    height = this.texture.tex.height;\n    max = Math.max(width, height);\n    w = width / max;\n    h = height / max;\n    s = 1 / Math.max(w * xscale, h * yscale);\n    w = w * (1 - one2one) + s * w * one2one;\n    h = h * (1 - one2one) + s * h * one2one;\n    return this.node.sampler('source', this.texture.tex).f('mixgamma', this.gamma).f('diva', this.diva).f('border_factor', active).val2('affine', this.mul, this.add).val2('size', w * xscale, h * yscale).val2('offset', (this.x - cx) * xscale, (this.y - cy) * yscale).draw();\n  };\n\n  return Window;\n\n})();\n\nreturn Windows = (function() {\n\n  function Windows(gl, gui, textures) {\n    var active, folder, gridsize, i, labels, maxx, maxy, minx, miny, texture, window, x, y, _i, _j, _len, _len1, _ref, _ref1,\n      _this = this;\n    this.gl = gl;\n    this.textures = textures;\n    this.prev = __bind(this.prev, this);\n\n    this.next = __bind(this.next, this);\n\n    this.guiLabelChange = __bind(this.guiLabelChange, this);\n\n    this.labelVisibilityChange = __bind(this.labelVisibilityChange, this);\n\n    gui.remember(this);\n    this.label = $('<div id=\"windowlabel\">test</div>').appendTo('#ui').hide();\n    this.show_all = false;\n    this.show_label = false;\n    this.needs_clear = $.browser.mozilla;\n    this.node = new Rendernode(this.gl, {\n      front: true,\n      program: get('window.shader'),\n      drawable: quad\n    });\n    this.windows = [];\n    this.labelmap = {};\n    labels = [];\n    gridsize = Math.ceil(Math.sqrt(this.textures.length));\n    _ref = this.textures;\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      texture = _ref[i];\n      x = i % gridsize;\n      y = gridsize - Math.floor(i / gridsize) - 1;\n      window = new Window(i, texture, this.node, x * 2.2, y * 2.2);\n      this.labelmap[window.label] = window;\n      this.windows.push(window);\n      labels.push(window.label);\n    }\n    minx = null;\n    maxx = null;\n    miny = null;\n    maxy = null;\n    _ref1 = this.windows;\n    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n      window = _ref1[_j];\n      minx = minx !== null ? Math.min(window.x, minx) : window.x;\n      maxx = maxx !== null ? Math.max(window.x, maxx) : window.x;\n      miny = miny !== null ? Math.min(window.y, miny) : window.y;\n      maxy = maxy !== null ? Math.max(window.y, maxy) : window.y;\n    }\n    this.cx = (minx + maxx) / 2;\n    this.cy = (miny + maxy) / 2;\n    this.full_scale = 1.9 / Math.min(maxx - minx + 2, maxy - miny + 2);\n    this.zoom = 0.0;\n    this.active = this.windows.length - 1;\n    keys.press('right', this.next);\n    keys.press('left', this.prev);\n    keys.press('down', function() {\n      var new_value;\n      new_value = _this.active + gridsize;\n      if (new_value < _this.windows.length) {\n        _this.active = new_value;\n      } else {\n        _this.active = _this.active % gridsize;\n      }\n      return _this.setActive();\n    });\n    keys.press('up', function() {\n      var new_value;\n      new_value = _this.active - gridsize;\n      if (new_value >= 0) {\n        _this.active = new_value;\n      } else {\n        new_value = gridsize * gridsize + new_value;\n        while (new_value >= _this.windows.length) {\n          new_value -= gridsize;\n        }\n        _this.active = new_value;\n      }\n      return _this.setActive();\n    });\n    keys.press('space', function() {\n      _this.show_all = !_this.show_all;\n      return _this.all_ctrl.setValue(_this.show_all);\n    });\n    keys.press('enter', function() {\n      _this.show_all = !_this.show_all;\n      return _this.all_ctrl.setValue(_this.show_all);\n    });\n    active = this.getActive();\n    this.x = active.x;\n    this.y = active.y;\n    folder = gui.addFolder('Views');\n    this.all_ctrl = folder.add(this, 'show_all').name('Overview');\n    folder.add(this, 'next').name('Next view');\n    folder.add(this, 'prev').name('Prev view');\n    this.window_label = active.label;\n    this.guiLabel = folder.add(this, 'window_label', labels).name('View').onChange(this.guiLabelChange);\n    folder.add(this, 'show_label').name('Labels').onChange(this.labelVisibilityChange);\n    this.guiLabelChange();\n  }\n\n  Windows.prototype.labelVisibilityChange = function() {\n    if (this.show_label) {\n      return this.label.clearQueue().fadeIn();\n    } else {\n      return this.label.clearQueue().fadeOut();\n    }\n  };\n\n  Windows.prototype.guiLabelChange = function() {\n    var window;\n    window = this.labelmap[this.window_label];\n    this.active = window.index;\n    return this.setActive();\n  };\n\n  Windows.prototype.getActive = function() {\n    return this.windows[this.active];\n  };\n\n  Windows.prototype.setActive = function() {\n    var text;\n    text = this.getActive().label;\n    this.window_label = text;\n    this.guiLabel.updateDisplay();\n    return this.label.text(text);\n  };\n\n  Windows.prototype.next = function() {\n    this.active = (this.active + 1) % this.windows.length;\n    return this.setActive();\n  };\n\n  Windows.prototype.prev = function() {\n    if (this.active === 0) {\n      this.active = this.windows.length - 1;\n    } else {\n      this.active -= 1;\n    }\n    return this.setActive();\n  };\n\n  Windows.prototype.step = function() {\n    var active, tx, ty;\n    active = this.getActive();\n    tx = active.x;\n    ty = active.y;\n    this.x = this.x + (tx - this.x) * 0.1;\n    this.y = this.y + (ty - this.y) * 0.1;\n    if (this.show_all) {\n      return this.zoom = this.zoom + (1 - this.zoom) * 0.1;\n    } else {\n      return this.zoom = this.zoom + (0 - this.zoom) * 0.1;\n    }\n  };\n\n  Windows.prototype.draw = function(gamma) {\n    var active, factor, height, width, window, xscale, yscale, _i, _len, _ref;\n    this.step();\n    if (this.needs_clear === true) {\n      this.gl.clearColor(0, 0, 0, 0);\n      this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n    }\n    this.node.start().f('gamma', gamma);\n    width = this.node.width;\n    height = this.node.height;\n    if (width > height) {\n      xscale = height / width;\n      yscale = 1;\n    } else {\n      xscale = 1;\n      yscale = width / height;\n    }\n    factor = 1.0 - this.zoom + this.zoom * this.full_scale;\n    xscale *= factor;\n    yscale *= factor;\n    active = this.getActive();\n    _ref = this.windows;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      window = _ref[_i];\n      if (window !== active) {\n        this.drawWindow(xscale, yscale, window, 0);\n      }\n    }\n    this.drawWindow(xscale, yscale, active, 1);\n    return this.node.end();\n  };\n\n  Windows.prototype.drawWindow = function(xscale, yscale, window, active) {\n    var dx, dy, l, one2one, x, y;\n    dx = window.x - this.x;\n    dy = window.y - this.y;\n    l = Math.sqrt(dx * dx + dy * dy);\n    if (l > 0) {\n      one2one = Math.min(1 / (l * 2), 1);\n    } else {\n      one2one = 1;\n    }\n    x = this.x * (1 - this.zoom) + this.cx * this.zoom;\n    y = this.y * (1 - this.zoom) + this.cy * this.zoom;\n    active = Math.pow(one2one, 2.0) * this.zoom;\n    return window.draw(xscale, yscale, one2one * (1 - this.zoom), x, y, active);\n  };\n\n  return Windows;\n\n})();\n});\n    \n    loader.define('/depth/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Blur, DeferredShadowMap, DepthRender, LightmappedShadowMap, Rendernode;\n\nRendernode = require('/rendernode');\n\nBlur = require('/blur');\n\nexports.DepthRender = DepthRender = (function() {\n\n  function DepthRender(gl, width, height, drawable, _arg) {\n    var blurred, floatExt;\n    blurred = (_arg != null ? _arg : {}).blurred;\n    if (blurred == null) {\n      blurred = false;\n    }\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.direct = new Rendernode(gl, {\n      width: width,\n      height: height,\n      program: get('depth.shader'),\n      drawable: drawable,\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      filter: blurred ? 'nearest' : 'linear',\n      type: floatExt.type,\n      cullFace: 'BACK'\n    });\n    if (blurred) {\n      this.blurred = new Blur(gl, {\n        width: width,\n        height: height,\n        type: floatExt.type\n      });\n    }\n    this.output = this.blurred ? this.blurred.output : this.direct;\n  }\n\n  DepthRender.prototype.update = function(proj, view) {\n    this.direct.start().clearBoth(0, 0, 0, 1).mat4('proj', proj).mat4('view', view).f('range', 42).draw().end();\n    if (this.blurred) {\n      return this.blurred.update(this.direct);\n    }\n  };\n\n  return DepthRender;\n\n})();\n\nexports.DeferredShadowMap = DeferredShadowMap = (function() {\n\n  function DeferredShadowMap(gl, _arg) {\n    var blurred, depthHeight, depthWidth, drawable;\n    drawable = _arg.drawable, depthWidth = _arg.depthWidth, depthHeight = _arg.depthHeight, this.eyeNormaldepth = _arg.eyeNormaldepth, this.light = _arg.light, this.camera = _arg.camera, blurred = _arg.blurred;\n    this.depth = new DepthRender(gl, depthWidth, depthHeight, drawable, {\n      blurred: blurred\n    });\n    this.output = new Rendernode(gl, {\n      program: get('deferred_shadow_map.shader'),\n      drawable: quad\n    });\n    this.updateDepth();\n  }\n\n  DeferredShadowMap.prototype.resize = function(width, height) {\n    return this.output.resize(width, height);\n  };\n\n  DeferredShadowMap.prototype.updateDepth = function() {\n    return this.depth.update(this.light.proj, this.light.view);\n  };\n\n  DeferredShadowMap.prototype.updateShadow = function() {\n    return this.output.start().clear(1, 0, 1).sampler('eye_normaldepth', this.eyeNormaldepth).sampler('light_depth', this.depth.output).mat4('inv_eye_proj', this.camera.inv_proj).mat4('inv_eye_view', this.camera.inv_view).mat4('light_view', this.light.view).mat4('light_proj', this.light.proj).mat3('light_rot', this.light.rot).draw().end();\n  };\n\n  return DeferredShadowMap;\n\n})();\n\nexports.LightmapShadowMap = LightmappedShadowMap = (function() {\n\n  function LightmappedShadowMap(gl, _arg) {\n    var blurred, depthHeight, depthWidth, drawable, lightmapSize;\n    drawable = _arg.drawable, depthWidth = _arg.depthWidth, depthHeight = _arg.depthHeight, lightmapSize = _arg.lightmapSize, this.light = _arg.light, blurred = _arg.blurred;\n    this.depth = new DepthRender(gl, depthWidth, depthHeight, drawable, {\n      blurred: blurred\n    });\n    if (lightmapSize == null) {\n      lightmapSize = 256;\n    }\n    this.output = new Rendernode(gl, {\n      width: lightmapSize,\n      height: lightmapSize,\n      program: get('lightmap_shadow_map.shader'),\n      drawable: drawable\n    });\n    this.update();\n  }\n\n  LightmappedShadowMap.prototype.update = function() {\n    this.depth.update(this.light.proj, this.light.view);\n    return this.output.start().sampler('light_depth', this.depth.output).mat4('light_view', this.light.view).mat4('light_proj', this.light.proj).mat3('light_rot', this.light.rot).draw().end();\n  };\n\n  return LightmappedShadowMap;\n\n})();\n});\n    \n    loader.define('/antialias/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar AntiAlias, Quad, Rendernode;\n\nRendernode = require('/rendernode');\n\nQuad = require('/webgl/quad');\n\nreturn AntiAlias = (function() {\n\n  function AntiAlias(gl, gui, source) {\n    var folder;\n    this.gl = gl;\n    this.source = source;\n    gui.remember(this);\n    this.node = new Rendernode(this.gl, {\n      program: get('fxaa3_11.shader'),\n      drawable: quad\n    });\n    this.subpixel_aa = 0.75;\n    this.contrast_treshold = 0.166;\n    this.edge_treshold = 0.0;\n    folder = gui.addFolder('Antialias');\n    folder.add(this, 'subpixel_aa', 0.0, 1.0).name('Subpixel aa');\n    folder.add(this, 'contrast_treshold', 0.063, 0.333).name('Contrast Treshold');\n    folder.add(this, 'edge_treshold', 0.0, 0.0833).name('Edge Treshold');\n  }\n\n  AntiAlias.prototype.apply = function() {\n    return this.node.start().f('subpixel_aa', this.subpixel_aa).f('contrast_treshold', this.contrast_treshold).f('edge_treshold', this.edge_treshold).clear().sampler('source', this.source).draw().end();\n  };\n\n  AntiAlias.prototype.resize = function(width, height) {\n    return this.node.resize(width, height);\n  };\n\n  return AntiAlias;\n\n})();\n});\n    \n    loader.define('/illumination/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar BounceModel, DepthRender, Illumination, LightmapShadowMap, Quad, Rendernode, Sphere, Texture2D, _ref;\n\nQuad = require('/webgl/quad');\n\nSphere = require('/webgl/sphere');\n\nTexture2D = require('/webgl/texture').Texture2D;\n\nRendernode = require('/rendernode');\n\n_ref = require('/depth'), DepthRender = _ref.DepthRender, LightmapShadowMap = _ref.LightmapShadowMap;\n\nBounceModel = require('bounce_model');\n\nreturn Illumination = (function() {\n\n  function Illumination(gl, sun, lighting, model, highresmodel, normaldepth, orientation, elevation, shconst) {\n    var floatExt;\n    this.gl = gl;\n    this.lighting = lighting;\n    this.shconst = shconst;\n    this.proj = new Mat4().perspective(90, 1, 0.01, 42);\n    this.view = new Mat4();\n    this.mapsize = 32;\n    this.probesize = 16;\n    this.generateProbes();\n    floatExt = this.gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.debug = new Rendernode(this.gl, {\n      program: get('debug.shader'),\n      drawable: new Sphere(this.gl, 0.6),\n      depthBuffer: true,\n      depthTest: true,\n      depthWrite: true,\n      cullFace: 'BACK',\n      type: floatExt.type\n    });\n    this.lightprobes = new Rendernode(this.gl, {\n      width: this.probesize * 6,\n      height: this.probesize * this.probes.length,\n      program: get('transfer.shader'),\n      drawable: quad,\n      filter: 'nearest',\n      type: floatExt.type\n    });\n    this.coefficients = new Rendernode(this.gl, {\n      width: 9,\n      height: this.probes.length,\n      program: get('harmonics.shader'),\n      drawable: quad,\n      filter: 'nearest',\n      type: floatExt.type\n    });\n    this.direct_light = new LightmapShadowMap(gl, {\n      drawable: model,\n      depthWidth: 128,\n      depthHeight: 128,\n      light: sun,\n      blurred: true\n    });\n    this.bounce = new Rendernode(this.gl, {\n      width: 256,\n      height: 256,\n      program: get('bounce.shader'),\n      drawable: new BounceModel(this.gl, model, this.probes),\n      type: floatExt.type,\n      blend: 'additive'\n    });\n    this.renderProbes(model, highresmodel);\n    this.update();\n  }\n\n  Illumination.prototype.generateProbes = function() {\n    var i, _i, _j, _results;\n    this.probes = [];\n    for (i = _i = 0; _i < 7; i = ++_i) {\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: 0\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: 5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 2.2,\n        z: -5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: 0\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: 5.5\n      });\n      this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 7.0,\n        z: -5.5\n      });\n    }\n    _results = [];\n    for (i = _j = 1; _j < 6; i = ++_j) {\n      _results.push(this.probes.push({\n        x: i * 4.5 - 3 * 4.5,\n        y: 12.5,\n        z: 0\n      }));\n    }\n    return _results;\n  };\n\n  Illumination.prototype.updateDirectLight = function() {\n    return this.direct_light.update();\n  };\n\n  Illumination.prototype.update = function() {\n    var i, _i, _ref1, _results;\n    this.bounce.start().clear(0, 0, 0, 1).f('gi_gain', this.lighting.giGain).val2('coefficients_size', this.coefficients.width, this.coefficients.height).fv('shconst', this.shconst.data).end();\n    this.lightprobes.start().vec3('sun_radiance', this.lighting.sun_radiance).vec3('sky_radiance', this.lighting.sky_radiance).sampler('texmap', this.texmap).sampler('diffusemap', this.diffusemap).sampler('bounce', this.bounce).sampler('lightmap', this.direct_light.output).draw().end();\n    this.coefficients.start().val2('lightprobes_size', this.lightprobes.width, this.lightprobes.height).sampler('lightprobes', this.lightprobes).fv('shconst', this.shconst.data).draw().end();\n    _results = [];\n    for (i = _i = 0, _ref1 = this.lighting.bounces - 1; 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) {\n      this.bounce.start().clear(0, 0, 0, 0).sampler('coefficients', this.coefficients).draw().end();\n      this.lightprobes.start().sampler('texmap', this.texmap).sampler('bounce', this.bounce).sampler('lightmap', this.direct_light.output).draw().end();\n      _results.push(this.coefficients.start().val2('lightprobes_size', this.lightprobes.width, this.lightprobes.height).sampler('lightprobes', this.lightprobes).draw().end());\n    }\n    return _results;\n  };\n\n  Illumination.prototype.renderProbes = function(model, highresmodel) {\n    var i, probe, _i, _j, _len, _len1, _ref1, _ref2;\n    if (get.exists('texmap.png')) {\n      this.texmap = new Texture2D(this.gl).bind().upload(get('texmap.png')).nearest().clampToEdge().unbind();\n    } else {\n      this.texmap = new Rendernode(this.gl, {\n        width: this.mapsize * 6,\n        height: this.mapsize * this.probes.length,\n        program: get('cubeprobe.shader'),\n        drawable: model,\n        depthTest: true,\n        depthWrite: true,\n        cullFace: 'BACK',\n        filter: 'nearest',\n        depthBuffer: true\n      });\n      this.texmap.start().clear(0, 0, 1);\n      this.texmap.mat4('proj', this.proj);\n      _ref1 = this.probes;\n      for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {\n        probe = _ref1[i];\n        this.renderProbe(i, this.texmap, null, probe.x, probe.y, probe.z);\n      }\n      this.texmap.end();\n      this.texmap = this.texmap.output;\n    }\n    if (get.exists('diffusemap.jpg')) {\n      return this.diffusemap = new Texture2D(this.gl).bind().upload(get('diffusemap.jpg')).nearest().clampToEdge().unbind();\n    } else {\n      this.diffusemap = new Rendernode(this.gl, {\n        width: this.mapsize * 6,\n        height: this.mapsize * this.probes.length,\n        program: get('cube_diffuse.shader'),\n        drawable: highresmodel,\n        depthTest: true,\n        depthWrite: true,\n        cullFace: 'BACK',\n        filter: 'nearest',\n        depthBuffer: true\n      });\n      this.diffusemap.start().clear(0, 0, 0);\n      this.diffusemap.mat4('proj', this.proj);\n      _ref2 = this.probes;\n      for (i = _j = 0, _len1 = _ref2.length; _j < _len1; i = ++_j) {\n        probe = _ref2[i];\n        this.renderProbe(i, this.diffusemap, 'diffuse_texture', probe.x, probe.y, probe.z);\n      }\n      this.diffusemap.end();\n      return this.diffusemap = this.diffusemap.output;\n    }\n  };\n\n  Illumination.prototype.renderProbe = function(i, node, texture_type, x, y, z) {\n    var offset, s;\n    s = this.mapsize;\n    offset = i * s;\n    this.view.identity().translateVal3(-x, -y, -z);\n    node.viewport(s * 0, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(180).translateVal3(-x, -y, -z);\n    node.viewport(s * 1, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(-90).translateVal3(-x, -y, -z);\n    node.viewport(s * 2, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatey(90).translateVal3(-x, -y, -z);\n    node.viewport(s * 3, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatex(-90).translateVal3(-x, -y, -z);\n    node.viewport(s * 4, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n    this.view.identity().rotatex(90).translateVal3(-x, -y, -z);\n    return node.viewport(s * 5, offset, s, s).mat4('view', this.view).drawModel(texture_type);\n  };\n\n  Illumination.prototype.drawDebug = function(camera, normaldepth) {\n    var i, probe, _i, _len, _ref1;\n    this.debug.start().clearBoth(0, 0, 0, 0).f('gi_gain', this.lighting.giGain).sampler('normaldepth', normaldepth).sampler('coefficients', this.coefficients).val2('coefficients_size', this.coefficients.width, this.coefficients.height).fv('shconst', this.shconst.data).mat4('proj', camera.proj).mat4('view', camera.view);\n    _ref1 = this.probes;\n    for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {\n      probe = _ref1[i];\n      this.debug.val3('offset', probe.x, probe.y, probe.z).f('index', i).draw();\n    }\n    return this.debug.end();\n  };\n\n  return Illumination;\n\n})();\n});\n    \n    loader.define('/illumination/bounce_model.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar BounceModel, pointTriangleDist,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\npointTriangleDist = require('/dist3d').pointTriangleDist;\n\nreturn BounceModel = (function(_super) {\n\n  __extends(BounceModel, _super);\n\n  BounceModel.prototype.attribs = ['position', 'texcoord', 'normal', 'lightprobe'];\n\n  BounceModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 12\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 12\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 12\n    }, {\n      name: 'lightprobe',\n      size: 4,\n      offset: 8,\n      stride: 12\n    }\n  ];\n\n  function BounceModel(gl, model, probes) {\n    var btx, bty, btz, det, dist, dot1, dot2, dot3, dx1, dx2, dx3, dy1, dy2, dy3, dz1, dz2, dz3, face_count, fnx, fny, fnz, i, l, nx1, nx2, nx3, ny1, ny2, ny3, nz1, nz2, nz3, probe, px, py, pz, result, start, tx, ty, tz, u1, u2, u3, v1, v2, v3, vali, vertex_count, verti, vertices, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i, _j, _len;\n    this.gl = gl;\n    BounceModel.__super__.constructor.call(this);\n    start = gettime();\n    vertices = model.vertices;\n    vertex_count = vertices.length / 8;\n    face_count = vertex_count / 3;\n    result = [];\n    for (i = _i = 0; 0 <= face_count ? _i < face_count : _i > face_count; i = 0 <= face_count ? ++_i : --_i) {\n      verti = i * 3;\n      vali = verti * 8;\n      x1 = vertices[vali + 0];\n      y1 = vertices[vali + 1];\n      z1 = vertices[vali + 2];\n      u1 = vertices[vali + 3];\n      v1 = vertices[vali + 4];\n      nx1 = vertices[vali + 5];\n      ny1 = vertices[vali + 6];\n      nz1 = vertices[vali + 7];\n      vali = verti * 8 + 8;\n      x2 = vertices[vali + 0];\n      y2 = vertices[vali + 1];\n      z2 = vertices[vali + 2];\n      u2 = vertices[vali + 3];\n      v2 = vertices[vali + 4];\n      nx2 = vertices[vali + 5];\n      ny2 = vertices[vali + 6];\n      nz2 = vertices[vali + 7];\n      vali = verti * 8 + 16;\n      x3 = vertices[vali + 0];\n      y3 = vertices[vali + 1];\n      z3 = vertices[vali + 2];\n      u3 = vertices[vali + 3];\n      v3 = vertices[vali + 4];\n      nx3 = vertices[vali + 5];\n      ny3 = vertices[vali + 6];\n      nz3 = vertices[vali + 7];\n      for (i = _j = 0, _len = probes.length; _j < _len; i = ++_j) {\n        probe = probes[i];\n        px = probe.x;\n        py = probe.y;\n        pz = probe.z;\n        dx1 = px - x1;\n        dy1 = py - y1;\n        dz1 = pz - z1;\n        l = Math.sqrt(dx1 * dx1 + dy1 * dy1 + dz1 * dz1);\n        dx1 /= l;\n        dy1 /= l;\n        dz1 /= l;\n        dot1 = dx1 * nx1 + dy1 * ny1 + dz1 * nz1;\n        dx2 = px - x2;\n        dy2 = py - y2;\n        dz2 = pz - z2;\n        l = Math.sqrt(dx2 * dx2 + dy2 * dy2 + dz2 * dz2);\n        dx2 /= l;\n        dy2 /= l;\n        dz2 /= l;\n        dot2 = dx2 * nx2 + dy2 * ny2 + dz2 * nz2;\n        dx3 = px - x3;\n        dy3 = py - y3;\n        dz3 = pz - z3;\n        l = Math.sqrt(dx3 * dx3 + dy3 * dy3 + dz3 * dz3);\n        dx3 /= l;\n        dy3 /= l;\n        dz3 /= l;\n        dot3 = dx3 * nx3 + dy3 * ny3 + dz3 * nz3;\n        tx = x2 - x1;\n        ty = y2 - y1;\n        tz = z2 - z1;\n        btx = x3 - x1;\n        bty = y3 - y1;\n        btz = z3 - z1;\n        fnx = ty * btz - tz * bty;\n        fny = tz * btx - tx * btz;\n        fnz = tx * bty - ty * btx;\n        l = Math.sqrt(fnx * fnx + fny * fny + fnz * fnz);\n        fnx /= l;\n        fny /= l;\n        fnz /= l;\n        det = fnx * x1 + fny * y1 + fnz * z1;\n        dist = Math.abs((fnx * px + fny * py + fnz * pz) - det);\n        if ((dot1 >= 0 || dot2 >= 0 || dot3 >= 0) && dist <= 5.0) {\n          if (pointTriangleDist([px, py, pz], [x1, y1, z1], [x2, y2, z2], [x3, y3, z3]) <= 5.0) {\n            result.push(x1, y1, z1, u1, v1, nx1, ny1, nz1, px, py, pz, i, x2, y2, z2, u2, v2, nx2, ny2, nz2, px, py, pz, i, x3, y3, z3, u3, v3, nx3, ny3, nz3, px, py, pz, i);\n          }\n        }\n      }\n    }\n    this.size = result.length / 12;\n    this.uploadList(result);\n  }\n\n  return BounceModel;\n\n})(require('/webgl/drawable'));\n});\n    \n    loader.define('/ssao/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Blur, Rendernode, SSAO;\n\nRendernode = require('/rendernode');\n\nBlur = require('/blur');\n\nreturn SSAO = (function() {\n\n  function SSAO(gl, normaldepth) {\n    var floatExt;\n    this.normaldepth = normaldepth;\n    floatExt = gl.getFloatExtension({\n      require: ['renderable', 'filterable']\n    });\n    this.moments = new Rendernode(gl, {\n      program: get('moments.shader'),\n      type: floatExt.type,\n      drawable: quad\n    });\n    this.blur = new Blur(gl, {\n      type: floatExt.type\n    });\n    this.output = new Rendernode(gl, {\n      program: get('ssao.shader'),\n      drawable: quad\n    });\n  }\n\n  SSAO.prototype.update = function() {\n    this.moments.start().sampler('normaldepth', this.normaldepth).f('range', 42).clear().draw().end();\n    this.blur.update(this.moments);\n    return this.output.start().sampler('normaldepth', this.normaldepth).sampler('momentsmap', this.blur.output).f('range', 42).clear().draw().end();\n  };\n\n  SSAO.prototype.resize = function(width, height) {\n    this.moments.resize(width / 2, height / 2);\n    this.blur.resize(width / 4, height / 4);\n    return this.output.resize(width, height);\n  };\n\n  return SSAO;\n\n})();\n});\n    \n    loader.define('/blur/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Blur, Rendernode;\n\nRendernode = require('/rendernode');\n\nreturn Blur = (function() {\n\n  function Blur(gl, _arg) {\n    var filter, height, type, width;\n    width = _arg.width, height = _arg.height, type = _arg.type, filter = _arg.filter;\n    if (type == null) {\n      type = gl.UNSIGNED_BYTE;\n    }\n    if (filter == null) {\n      filter = 'linear';\n    }\n    this.output = new Rendernode(gl, {\n      width: width,\n      height: height,\n      program: get('blur.shader'),\n      drawable: quad,\n      filter: filter,\n      type: type\n    });\n  }\n\n  Blur.prototype.update = function(source) {\n    return this.output.start().sampler('source', source).draw().end();\n  };\n\n  Blur.prototype.resize = function(width, height) {\n    return this.output.resize(width, height);\n  };\n\n  return Blur;\n\n})();\n});\n    \n    loader.define('/model/module.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar LowresModel, Materials, Model, Texture2D,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nTexture2D = require('/webgl/texture').Texture2D;\n\nMaterials = Materials = (function() {\n\n  Materials.prototype.createTexture = function(path) {\n    var image, texture;\n    texture = this.texture_cache[path];\n    if (!texture) {\n      image = get(path);\n      texture = new Texture2D(this.gl).bind().upload(image).mipmap().repeat().unbind();\n      this.texture_cache[path] = texture;\n    }\n    return texture;\n  };\n\n  function Materials(gl) {\n    var definition, diffuse, jpgbump, luma, pngbump, specular, _i, _len, _ref;\n    this.gl = gl;\n    this.texture_cache = {};\n    this.definitions = get('materials.json');\n    this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, true);\n    _ref = this.definitions;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      definition = _ref[_i];\n      diffuse = \"diffuse/\" + definition.diffuse_texture;\n      jpgbump = \"bump/\" + definition.bumpmap;\n      pngbump = jpgbump.replace('.jpg', '.png');\n      definition.diffuse_texture = this.createTexture(diffuse);\n      specular = definition.specular_color;\n      luma = (specular.r + specular.g + specular.b) / 3;\n      definition.specularity = luma * definition.specularity;\n      if (get.exists(pngbump)) {\n        definition.bumpmap = this.createTexture(pngbump);\n      } else if (get.exists(jpgbump)) {\n        definition.bumpmap = this.createTexture(jpgbump);\n      } else {\n        definition.bumpmap = definition.diffuse_texture;\n      }\n    }\n    this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false);\n    this.diffuse_texture = this.sortById('diffuse_texture');\n    this.bumpmap = this.sortById('bumpmap');\n  }\n\n  Materials.prototype.sortById = function(type) {\n    var definition, result;\n    result = (function() {\n      var _i, _len, _ref, _results;\n      _ref = this.definitions;\n      _results = [];\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        definition = _ref[_i];\n        _results.push(definition);\n      }\n      return _results;\n    }).call(this);\n    result.sort(function(a, b) {\n      return a[type].id - b[type].id;\n    });\n    return result;\n  };\n\n  return Materials;\n\n})();\n\nexports.LowresModel = LowresModel = (function(_super) {\n\n  __extends(LowresModel, _super);\n\n  LowresModel.prototype.attribs = ['position', 'texcoord', 'normal'];\n\n  LowresModel.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 8\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 8\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 8\n    }\n  ];\n\n  function LowresModel(gl) {\n    this.gl = gl;\n    LowresModel.__super__.constructor.call(this);\n    this.vertices = new Float32Array(get('lowres.vertices'));\n    this.size = this.vertices.length / 8;\n    this.upload(this.vertices);\n  }\n\n  return LowresModel;\n\n})(require('/webgl/drawable'));\n\nexports.Model = Model = (function(_super) {\n\n  __extends(Model, _super);\n\n  Model.prototype.attribs = ['position', 'texcoord', 'normal'];\n\n  Model.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 8\n    }, {\n      name: 'texcoord',\n      size: 2,\n      offset: 3,\n      stride: 8\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 5,\n      stride: 8\n    }\n  ];\n\n  function Model(gl) {\n    var buffer, indices, vertices;\n    this.gl = gl;\n    Model.__super__.constructor.call(this);\n    this.materials = new Materials(this.gl);\n    indices = new Uint16Array(get('sponza.indices'));\n    vertices = new Float32Array(get('sponza.vertices'));\n    this.size = indices.length;\n    this.max_angle = Math.cos(Math.PI * 2 * (43 / 360));\n    this.computeVertexFaces(indices, vertices);\n    this.computeFaceNormals(indices, vertices);\n    buffer = this.calculateVertices(indices, vertices);\n    this.upload(buffer);\n  }\n\n  Model.prototype.computeVertexFaces = function(indices, vertices) {\n    var c1, c2, c3, count, counts, end, face_count, face_index, idx1, idx2, idx3, index, iv, max, start, vertex_count, vertex_faces, _i, _j, _k, _len, _len1;\n    start = gettime();\n    vertex_count = vertices.length / 5;\n    counts = new Uint8Array(vertex_count);\n    for (_i = 0, _len = indices.length; _i < _len; _i++) {\n      index = indices[_i];\n      counts[index] += 1;\n    }\n    max = 0;\n    for (_j = 0, _len1 = counts.length; _j < _len1; _j++) {\n      count = counts[_j];\n      if (count > max) {\n        max = count;\n      }\n    }\n    this.max_count = max;\n    vertex_faces = new Uint32Array(max * vertex_count);\n    counts = new Uint8Array(vertex_count);\n    face_count = indices.length / 3;\n    for (face_index = _k = 0; 0 <= face_count ? _k < face_count : _k > face_count; face_index = 0 <= face_count ? ++_k : --_k) {\n      iv = face_index * 3;\n      idx1 = indices[iv];\n      idx2 = indices[iv + 1];\n      idx3 = indices[iv + 2];\n      c1 = counts[idx1]++;\n      c2 = counts[idx2]++;\n      c3 = counts[idx3]++;\n      vertex_faces[idx1 * max + c1] = face_index;\n      vertex_faces[idx2 * max + c2] = face_index;\n      vertex_faces[idx3 * max + c3] = face_index;\n    }\n    end = gettime();\n    this.vertex_face_count = counts;\n    return this.vertex_faces = vertex_faces;\n  };\n\n  Model.prototype.computeFaceNormals = function(indices, vertices) {\n    var btx, bty, btz, end, face_count, i, i1, i2, i3, iv, l, normals, nx, ny, nz, start, tx, ty, tz, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i;\n    start = gettime();\n    face_count = indices.length / 3;\n    normals = new Float32Array(face_count * 3);\n    for (i = _i = 0; 0 <= face_count ? _i < face_count : _i > face_count; i = 0 <= face_count ? ++_i : --_i) {\n      iv = i * 3;\n      i1 = indices[iv];\n      i2 = indices[iv + 1];\n      i3 = indices[iv + 2];\n      x1 = vertices[i1 * 5];\n      y1 = vertices[i1 * 5 + 1];\n      z1 = vertices[i1 * 5 + 2];\n      x2 = vertices[i2 * 5];\n      y2 = vertices[i2 * 5 + 1];\n      z2 = vertices[i2 * 5 + 2];\n      x3 = vertices[i3 * 5];\n      y3 = vertices[i3 * 5 + 1];\n      z3 = vertices[i3 * 5 + 2];\n      tx = x2 - x1;\n      ty = y2 - y1;\n      tz = z2 - z1;\n      btx = x3 - x1;\n      bty = y3 - y1;\n      btz = z3 - z1;\n      nx = ty * btz - tz * bty;\n      ny = tz * btx - tx * btz;\n      nz = tx * bty - ty * btx;\n      l = Math.sqrt(nx * nx + ny * ny + nz * nz);\n      nx /= l;\n      ny /= l;\n      nz /= l;\n      normals[iv + 0] = nx;\n      normals[iv + 1] = ny;\n      normals[iv + 2] = nz;\n    }\n    this.normals = normals;\n    return end = gettime();\n  };\n\n  Model.prototype.getNormal = function(face_index, vertex_index) {\n    var c, cos, l, nx, ny, nz, rx, ry, rz, vfidx, x, y, z, _i, _ref;\n    rx = this.normals[face_index * 3 + 0];\n    ry = this.normals[face_index * 3 + 1];\n    rz = this.normals[face_index * 3 + 2];\n    nx = 0;\n    ny = 0;\n    nz = 0;\n    for (c = _i = 0, _ref = this.vertex_face_count[vertex_index]; 0 <= _ref ? _i < _ref : _i > _ref; c = 0 <= _ref ? ++_i : --_i) {\n      vfidx = this.vertex_faces[vertex_index * this.max_count + c];\n      x = this.normals[vfidx * 3 + 0];\n      y = this.normals[vfidx * 3 + 1];\n      z = this.normals[vfidx * 3 + 2];\n      cos = rx * x + ry * y + rz * z;\n      if (cos > this.max_angle) {\n        nx = x;\n        ny = y;\n        nz = z;\n      }\n    }\n    l = Math.sqrt(nx * nx + ny * ny + nz * nz);\n    return [nx / l, ny / l, nz / l];\n  };\n\n  Model.prototype.calculateVertices = function(indices, vertices, normals) {\n    var end, i, i1, i2, i3, iv, nx, ny, nz, result, start, u1, u2, u3, v1, v2, v3, x1, x2, x3, y1, y2, y3, z1, z2, z3, _i, _ref, _ref1, _ref2, _ref3;\n    start = gettime();\n    result = new Float32Array(indices.length * 8);\n    for (i = _i = 0, _ref = indices.length / 3; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n      iv = i * 3;\n      i1 = indices[iv];\n      i2 = indices[iv + 1];\n      i3 = indices[iv + 2];\n      x1 = vertices[i1 * 5];\n      y1 = vertices[i1 * 5 + 1];\n      z1 = vertices[i1 * 5 + 2];\n      u1 = vertices[i1 * 5 + 3];\n      v1 = vertices[i1 * 5 + 4];\n      x2 = vertices[i2 * 5];\n      y2 = vertices[i2 * 5 + 1];\n      z2 = vertices[i2 * 5 + 2];\n      u2 = vertices[i2 * 5 + 3];\n      v2 = vertices[i2 * 5 + 4];\n      x3 = vertices[i3 * 5];\n      y3 = vertices[i3 * 5 + 1];\n      z3 = vertices[i3 * 5 + 2];\n      u3 = vertices[i3 * 5 + 3];\n      v3 = vertices[i3 * 5 + 4];\n      _ref1 = this.getNormal(i, i1), nx = _ref1[0], ny = _ref1[1], nz = _ref1[2];\n      result[(iv + 0) * 8 + 0] = x1;\n      result[(iv + 0) * 8 + 1] = y1;\n      result[(iv + 0) * 8 + 2] = z1;\n      result[(iv + 0) * 8 + 3] = u1;\n      result[(iv + 0) * 8 + 4] = v1;\n      result[(iv + 0) * 8 + 5] = nx;\n      result[(iv + 0) * 8 + 6] = ny;\n      result[(iv + 0) * 8 + 7] = nz;\n      _ref2 = this.getNormal(i, i2), nx = _ref2[0], ny = _ref2[1], nz = _ref2[2];\n      result[(iv + 1) * 8 + 0] = x2;\n      result[(iv + 1) * 8 + 1] = y2;\n      result[(iv + 1) * 8 + 2] = z2;\n      result[(iv + 1) * 8 + 3] = u2;\n      result[(iv + 1) * 8 + 4] = v2;\n      result[(iv + 1) * 8 + 5] = nx;\n      result[(iv + 1) * 8 + 6] = ny;\n      result[(iv + 1) * 8 + 7] = nz;\n      _ref3 = this.getNormal(i, i3), nx = _ref3[0], ny = _ref3[1], nz = _ref3[2];\n      result[(iv + 2) * 8 + 0] = x3;\n      result[(iv + 2) * 8 + 1] = y3;\n      result[(iv + 2) * 8 + 2] = z3;\n      result[(iv + 2) * 8 + 3] = u3;\n      result[(iv + 2) * 8 + 4] = v3;\n      result[(iv + 2) * 8 + 5] = nx;\n      result[(iv + 2) * 8 + 6] = ny;\n      result[(iv + 2) * 8 + 7] = nz;\n    }\n    end = gettime();\n    return result;\n  };\n\n  'draw: (shader) ->\\n    if shader then @setPointersForShader shader\\n    for material in @materials\\n        #@gl.drawArrays @mode, @first, @size\\n        @gl.drawArrays @mode, material.start, material.size\\n    if shader then @disableAttribs shader\\n    return @';\n\n\n  return Model;\n\n})(require('/webgl/drawable'));\n});\n    \n    loader.define('/webgl-nuke-vendor-prefix.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar getExtension, getSupportedExtensions, vendorRe, vendors,\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\nif (window.WebGLRenderingContext != null) {\n  vendors = ['WEBKIT', 'MOZ', 'MS', 'O'];\n  vendorRe = /^WEBKIT_(.*)|MOZ_(.*)|MS_(.*)|O_(.*)/;\n  getExtension = WebGLRenderingContext.prototype.getExtension;\n  WebGLRenderingContext.prototype.getExtension = function(name) {\n    var extobj, match, vendor, _i, _len;\n    match = name.match(vendorRe);\n    if (match !== null) {\n      name = match[1];\n    }\n    extobj = getExtension.call(this, name);\n    if (extobj === null) {\n      for (_i = 0, _len = vendors.length; _i < _len; _i++) {\n        vendor = vendors[_i];\n        extobj = getExtension.call(this, vendor + '_' + name);\n        if (extobj !== null) {\n          return extobj;\n        }\n      }\n      return null;\n    } else {\n      return extobj;\n    }\n  };\n  getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;\n  WebGLRenderingContext.prototype.getSupportedExtensions = function() {\n    var extension, match, result, supported, _i, _len;\n    supported = getSupportedExtensions.call(this);\n    result = [];\n    for (_i = 0, _len = supported.length; _i < _len; _i++) {\n      extension = supported[_i];\n      match = extension.match(vendorRe);\n      if (match !== null) {\n        extension = match[1];\n      }\n      if (__indexOf.call(result, extension) < 0) {\n        result.push(extension);\n      }\n    }\n    return result;\n  };\n}\n});\n    \n    loader.define('/loading.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar bar, container, hidden, label, loading, makeBar, ui;\n\nui = $('#ui');\n\nhidden = true;\n\ncontainer = $('<div></div>').css({\n  position: 'absolute',\n  top: '50%',\n  left: '50%',\n  width: 200,\n  height: 40,\n  marginLeft: -100,\n  marginTop: -20\n});\n\nlabel = $('<div></div>').appendTo(container).css({\n  position: 'absolute',\n  top: 0,\n  left: 0,\n  width: 200,\n  height: 20,\n  textAlign: 'center',\n  color: 'white'\n});\n\nloading = $('<div></div>').appendTo(container).css({\n  position: 'absolute',\n  top: 20,\n  left: 0,\n  width: 200,\n  height: 20,\n  border: '1px solid white'\n});\n\nbar = null;\n\nmakeBar = function() {\n  loading.empty();\n  return bar = $('<div></div>').appendTo(loading).css({\n    position: 'absolute',\n    top: 0,\n    left: 0,\n    width: 0,\n    height: 20,\n    backgroundColor: 'white',\n    '-webkit-transition': 'width 0.7s'\n  });\n};\n\nexports.show = function(text) {\n  label.text(text);\n  makeBar();\n  return container.fadeIn('slow').appendTo(ui);\n};\n\nexports.hide = function() {\n  return container.fadeOut('slow', function() {\n    return container.detach();\n  });\n};\n\nexports.progress = function(factor) {\n  return bar.width(factor * 200);\n};\n});\n    \n    loader.define('/geometry.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\n\nexports.AABB = (function() {\n\n  function AABB(xmin, xmax, ymin, ymax, zmin, zmax) {\n    this.xmin = xmin;\n    this.xmax = xmax;\n    this.ymin = ymin;\n    this.ymax = ymax;\n    this.zmin = zmin;\n    this.zmax = zmax;\n  }\n\n  AABB.prototype.ray_intersect = function(ray) {\n    var d, inv_x, inv_y, inv_z, o, tmax, tmin, ymax, ymin, zmax, zmin, _ref, _ref1, _ref2;\n    o = ray.origin;\n    d = ray.direction;\n    inv_x = 1.0 / d.x;\n    tmin = (this.xmin - o.x) * inv_x;\n    tmax = (this.xmax - o.x) * inv_x;\n    if (inv_x < 0) {\n      _ref = [tmax, tmin], tmin = _ref[0], tmax = _ref[1];\n    }\n    inv_y = 1.0 / d.y;\n    ymin = (this.ymin - o.y) * inv_y;\n    ymax = (this.ymax - o.y) * inv_y;\n    if (inv_y < 0) {\n      _ref1 = [ymax, ymin], ymin = _ref1[0], ymax = _ref1[1];\n    }\n    if (tmin > ymax || ymin > tmax) {\n      return null;\n    }\n    if (ymin > tmin) {\n      tmin = ymin;\n    }\n    if (ymax < tmax) {\n      tmax = ymax;\n    }\n    inv_z = 1.0 / d.z;\n    zmin = (this.zmin - o.z) * inv_z;\n    zmax = (this.zmax - o.z) * inv_z;\n    if (inv_z < 0) {\n      _ref2 = [zmax, zmin], zmin = _ref2[0], zmax = _ref2[1];\n    }\n    if (tmin > zmax || zmin > tmax) {\n      return null;\n    }\n    if (zmin > tmin) {\n      tmin = zmin;\n    }\n    if (zmax < tmax) {\n      tmax = zmax;\n    }\n    return [tmin, tmax];\n  };\n\n  return AABB;\n\n})();\n\nexports.Ray = (function() {\n\n  function Ray(origin, direction) {\n    var _ref, _ref1;\n    this.origin = origin;\n    this.direction = direction;\n    if ((_ref = this.origin) == null) {\n      this.origin = new Vec4();\n    }\n    if ((_ref1 = this.direction) == null) {\n      this.direction = new Vec4();\n    }\n  }\n\n  Ray.prototype.interpolate = function(interval, vector) {\n    var d, o, v;\n    if (vector == null) {\n      vector = new Vec4();\n    }\n    o = this.origin;\n    d = this.direction;\n    v = vector;\n    v.x = o.x + d.x * interval;\n    v.y = o.y + d.y * interval;\n    v.z = o.z + d.z * interval;\n    v.w = o.w + d.w * interval;\n    return vector;\n  };\n\n  Ray.prototype.ray_nearest = function(ray) {\n    var U, V, W, a, b, c, d, det, e, s, t;\n    W = this.origin.sub(ray.origin, new Vec4);\n    U = this.direction;\n    V = ray.direction;\n    a = U.dot(U);\n    b = U.dot(V);\n    c = V.dot(V);\n    d = U.dot(W);\n    e = V.dot(W);\n    det = a * c - b * b;\n    if (det === 0) {\n      return null;\n    }\n    s = (b * e - c * d) / det;\n    t = (a * e - b * d) / det;\n    return [s, t];\n  };\n\n  Ray.prototype.point_distance = function(point) {\n    var W, s;\n    W = point.sub(this.origin, new Vec4);\n    s = W.dot(this.direction) / this.direction.dot(this.direction);\n    W.x -= this.direction.x * s;\n    W.y -= this.direction.y * s;\n    W.z -= this.direction.z * s;\n    return Math.sqrt(W.dot(W));\n  };\n\n  return Ray;\n\n})();\n\nexports.get_mouseray = function(x, y, inv_proj, inv_view, ray) {\n  if (ray == null) {\n    ray = new exports.Ray;\n  }\n  inv_proj.mulVal4(x, y, -1, 1, ray.direction);\n  inv_view.mulVec3(ray.direction);\n  ray.direction.w = 0;\n  inv_view.mulVal4(0, 0, 0, 1, ray.origin);\n  return ray;\n};\n});\n    \n    loader.define('/keys.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar key_handlers, keymap, keys;\n\nkeymap = {\n  87: 'w',\n  65: 'a',\n  83: 's',\n  68: 'd',\n  81: 'q',\n  69: 'e',\n  37: 'left',\n  39: 'right',\n  38: 'up',\n  40: 'down',\n  13: 'enter',\n  27: 'esc',\n  32: 'space',\n  8: 'backspace',\n  16: 'shift',\n  17: 'ctrl',\n  18: 'alt',\n  91: 'start',\n  0: 'altc',\n  20: 'caps',\n  9: 'tab',\n  49: 'key1',\n  50: 'key2',\n  51: 'key3',\n  52: 'key4'\n};\n\nkey_handlers = {};\n\nkeys = {\n  press: function(name, callback) {\n    var handlers;\n    handlers = key_handlers[name] = key_handlers[name] || [];\n    return handlers.push(callback);\n  }\n};\n\n$(document).keydown(function(event) {\n  var handler, handlers, name, _i, _len, _results;\n  if (event.target === document.body) {\n    name = keymap[event.which];\n    keys[name] = true;\n    handlers = key_handlers[name];\n    if (handlers) {\n      _results = [];\n      for (_i = 0, _len = handlers.length; _i < _len; _i++) {\n        handler = handlers[_i];\n        _results.push(handler());\n      }\n      return _results;\n    }\n  }\n});\n\n$(document).keyup(function(event) {\n  var name;\n  name = keymap[event.which];\n  return keys[name] = false;\n});\n\nreturn keys;\n});\n    \n    loader.define('/camera.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Camera, FlyCam, GameCam, MouseDrag, Orbit, keys,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nkeys = require('keys');\n\nMouseDrag = (function() {\n\n  function MouseDrag(which) {\n    var _this = this;\n    this.which = which;\n    this.x = 0;\n    this.y = 0;\n    this.lx = 0;\n    this.ly = 0;\n    this.pressed = false;\n    if (navigator.appVersion.indexOf('Mac') !== -1) {\n      $('#ui').bind('mousewheel', function(event) {\n        event.preventDefault();\n        event.stopImmediatePropagation();\n        event.stopPropagation();\n        _this.x += event.originalEvent.wheelDeltaX * 0.25;\n        _this.y += event.originalEvent.wheelDeltaY * 0.25;\n        return false;\n      });\n    }\n    $('#ui').mousedown(function(event) {\n      if (event.which === _this.which) {\n        _this.lx = event.pageX;\n        _this.ly = event.pageY;\n        _this.pressed = true;\n      }\n      return void 0;\n    });\n    $(document).mouseup(function() {\n      _this.pressed = false;\n      return void 0;\n    });\n    $(document).mousemove(function(event) {\n      var x, y;\n      if (_this.pressed && event.which === _this.which) {\n        x = event.pageX;\n        y = event.pageY;\n        _this.x += x - _this.lx;\n        _this.y += y - _this.ly;\n        _this.lx = x;\n        _this.ly = y;\n        return false;\n      }\n      return void 0;\n    });\n  }\n\n  MouseDrag.prototype.reset = function() {\n    this.x = 0;\n    return this.y = 0;\n  };\n\n  return MouseDrag;\n\n})();\n\nCamera = (function() {\n\n  function Camera(delta, near, far) {\n    this.delta = delta != null ? delta : 1 / 180;\n    this.near = near != null ? near : 0.1;\n    this.far = far != null ? far : 1000;\n    this.last_gui_update = gettime();\n    this.time = gettime();\n    this.proj = new Mat4();\n    this.inv_proj = new Mat4();\n    this.view = new Mat4();\n    this.inv_view = new Mat4();\n    this.rot = new Mat3();\n    this.inv_rot = new Mat3();\n    this.acc = new Vec3();\n  }\n\n  Camera.prototype.aspect = function(width, height) {\n    this.proj.perspective(75, width / height, this.near, this.far);\n    return this.inv_proj.inversePerspective(75, width / height, this.near, this.far);\n  };\n\n  Camera.prototype.step = function() {\n    this.accelerate();\n    this.limit();\n    this.move();\n    this.limit();\n    return this.time += this.delta;\n  };\n\n  Camera.prototype.update = function() {\n    var now;\n    now = gettime();\n    if (now - this.last_gui_update > 0.5) {\n      this.guiUpdate();\n      this.last_gui_update = now;\n    }\n    if (now - this.time > this.delta * 30) {\n      this.time = now - this.delta * 30;\n    }\n    while (this.time < now) {\n      this.step();\n    }\n    this.finish();\n    this.view.invert(this.inv_view.identity());\n    this.view.toMat3(this.rot.identity());\n    return this.inv_view.toMat3(this.inv_rot.identity());\n  };\n\n  Camera.prototype.limit = function() {};\n\n  Camera.prototype.guiUpdate = function() {};\n\n  return Camera;\n\n})();\n\nexports.GameCam = GameCam = (function(_super) {\n\n  __extends(GameCam, _super);\n\n  function GameCam(_arg) {\n    var delta, x, y, z, _ref, _ref1, _ref2,\n      _this = this;\n    _ref = _arg != null ? _arg : {}, this.sl = _ref.sl, this.sr = _ref.sr, delta = _ref.delta, x = _ref.x, y = _ref.y, z = _ref.z;\n    GameCam.__super__.constructor.call(this, delta);\n    this.realpos = new Vec4();\n    if ((_ref1 = this.sl) == null) {\n      this.sl = 200;\n    }\n    if ((_ref2 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if (x == null) {\n      x = 0;\n    }\n    if (y == null) {\n      y = 0;\n    }\n    if (z == null) {\n      z = 0;\n    }\n    this.mouse = new MouseDrag(3);\n    this.target_height = 0;\n    this.height = 0;\n    this.x = x;\n    this.lx = x;\n    this.z = z;\n    this.lz = z;\n    this.o = 0;\n    this.lo = 0;\n    this.d = 0;\n    this.ld = 0;\n    this.ad = 0;\n    $(document).bind('mousewheel', function(event) {\n      event.preventDefault();\n      event.stopImmediatePropagation();\n      event.stopPropagation();\n      _this.ad -= event.originalEvent.wheelDeltaY;\n      return false;\n    });\n  }\n\n  GameCam.prototype.accelerate = function() {\n    var ax, az, ctrl_x, ctrl_y, ctrl_z, move, sl, sr;\n    sl = this.delta * this.delta * this.sl;\n    sr = this.delta * this.delta * this.sr;\n    ctrl_x = keys.a ? -1 : keys.d ? 1 : 0;\n    ctrl_y = keys.q ? -1 : keys.e ? 1 : 0;\n    ctrl_z = keys.w ? -1 : keys.s ? 1 : 0;\n    ax = ctrl_x * sl;\n    az = ctrl_z * sl;\n    this.rot.identity().rotatey(-this.o).mulVal3(ax, 0, az, this.acc);\n    this.x += this.acc.x;\n    this.z += this.acc.z;\n    this.o += this.mouse.x * sr;\n    this.d += this.ad * this.delta * this.delta * 20;\n    move = this.delta * this.delta * 4000;\n    if (move > 1) {\n      move = 1;\n    }\n    return this.height = this.height + (this.target_height - this.height) * move;\n  };\n\n  GameCam.prototype.move = function() {\n    var d, o, retl, retr, x, z;\n    retl = 0.97;\n    retr = 0.94;\n    x = this.x + (this.x - this.lx) * retl;\n    z = this.z + (this.z - this.lz) * retl;\n    d = this.d + (this.d - this.ld) * retl;\n    o = this.o + (this.o - this.lo) * retr;\n    this.lx = this.x;\n    this.x = x;\n    this.lz = this.z;\n    this.z = z;\n    this.lo = this.o;\n    this.o = o;\n    this.ld = this.d;\n    return this.d = d;\n  };\n\n  GameCam.prototype.limit = function() {\n    var high, low;\n    if (this.d < 0) {\n      this.d = 0;\n    } else if (this.d > 30) {\n      this.d = 30;\n    }\n    high = 128 + 64;\n    low = 128 - 64;\n    if (this.x < low) {\n      this.x = low;\n    } else if (this.x > high) {\n      this.x = high;\n    }\n    if (this.z < low) {\n      return this.z = low;\n    } else if (this.z > high) {\n      return this.z = high;\n    }\n  };\n\n  GameCam.prototype.finish = function() {\n    this.mouse.reset();\n    this.ad = 0;\n    return this.view.identity().translateVal3(0, 0, -this.d - 5).rotatex(25 + (this.d / 30) * 40).rotatey(this.o).translateVal3(-this.x, -this.height, -this.z);\n  };\n\n  GameCam.prototype.update = function(picker) {\n    var diff, h1, h2, real_height;\n    this.view.identity().translateVal3(0, 0, -this.d - 5).rotatex(25 + (this.d / 30) * 40).rotatey(this.o).translateVal3(-this.x, 0, -this.z);\n    this.view.invert(this.inv_view.identity());\n    h1 = picker.getHeight(this.x, this.z);\n    this.inv_view.mulVal4(0, 0, 0, 1, this.realpos);\n    h2 = picker.getHeight(this.realpos.x, this.realpos.z) + 2;\n    real_height = h1 + this.realpos.y;\n    if (real_height < h2) {\n      diff = h2 - real_height;\n      this.target_height = h1 + diff;\n    } else {\n      this.target_height = h1;\n    }\n    return GameCam.__super__.update.call(this);\n  };\n\n  return GameCam;\n\n})(Camera);\n\nexports.Orbit = Orbit = (function(_super) {\n\n  __extends(Orbit, _super);\n\n  function Orbit(_arg) {\n    var delta, x, y, z, _ref, _ref1, _ref2;\n    _ref = _arg != null ? _arg : {}, this.sr = _ref.sr, delta = _ref.delta, x = _ref.x, y = _ref.y, z = _ref.z, this.dist = _ref.dist;\n    Orbit.__super__.constructor.call(this, delta);\n    if ((_ref1 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if ((_ref2 = this.dist) == null) {\n      this.dist = 0.6;\n    }\n    this.mouse = new MouseDrag(1);\n    this.o = 0;\n    this.lo = 0;\n    this.p = 0;\n    this.lp = 0;\n  }\n\n  Orbit.prototype.accelerate = function() {\n    var sr;\n    sr = this.delta * this.delta * this.sr;\n    this.o += this.mouse.x * sr;\n    return this.p += this.mouse.y * sr;\n  };\n\n  Orbit.prototype.move = function() {\n    var o, p, retr;\n    retr = 0.94;\n    o = this.o + (this.o - this.lo) * retr;\n    p = this.p + (this.p - this.lp) * retr;\n    this.lo = this.o;\n    this.o = o;\n    this.lp = this.p;\n    return this.p = p;\n  };\n\n  Orbit.prototype.finish = function() {\n    return this.mouse.reset();\n  };\n\n  Orbit.prototype.update = function() {\n    this.view.identity().translateVal3(0, 0, -this.dist).rotatex(this.p).rotatey(this.o);\n    this.view.invert(this.inv_view.identity());\n    return Orbit.__super__.update.call(this);\n  };\n\n  return Orbit;\n\n})(Camera);\n\nexports.FlyCam = FlyCam = (function(_super) {\n\n  __extends(FlyCam, _super);\n\n  function FlyCam(_arg) {\n    var delta, far, folder, lookbutton, near, o, p, x, y, z, _ref, _ref1, _ref2;\n    _ref = _arg != null ? _arg : {}, this.sl = _ref.sl, this.gui = _ref.gui, this.sr = _ref.sr, delta = _ref.delta, near = _ref.near, far = _ref.far, lookbutton = _ref.lookbutton, x = _ref.x, y = _ref.y, z = _ref.z, o = _ref.o, p = _ref.p;\n    this.guiChanged = __bind(this.guiChanged, this);\n\n    FlyCam.__super__.constructor.call(this, delta, near, far);\n    if ((_ref1 = this.sl) == null) {\n      this.sl = 50;\n    }\n    if ((_ref2 = this.sr) == null) {\n      this.sr = 100;\n    }\n    if (lookbutton == null) {\n      lookbutton = 1;\n    }\n    if (x == null) {\n      x = 0;\n    }\n    if (y == null) {\n      y = 0;\n    }\n    if (z == null) {\n      z = 0;\n    }\n    if (o == null) {\n      o = 0;\n    }\n    if (p == null) {\n      p = 0;\n    }\n    this.mouse = new MouseDrag(lookbutton);\n    this.x = x;\n    this.lx = x;\n    this.y = y;\n    this.ly = y;\n    this.z = z;\n    this.lz = z;\n    this.o = o;\n    this.lo = o;\n    this.p = p;\n    this.lp = p;\n    folder = this.gui.addFolder('Camera');\n    this.gui.remember(this);\n    this.xgui = folder.add(this, 'x', -30.0, 30.0).onChange(this.guiChanged);\n    this.ygui = folder.add(this, 'y', -30.0, 30.0).onChange(this.guiChanged);\n    this.zgui = folder.add(this, 'z', -30.0, 30.0).onChange(this.guiChanged);\n    this.go = this.o;\n    this.ogui = folder.add(this, 'go', 0.0, 360.0).name('Orientation').onChange(this.guiChanged);\n    this.pgui = folder.add(this, 'p', -80.0, 80.0).name('Pitch').onChange(this.guiChanged);\n    this.guiChanged();\n  }\n\n  FlyCam.prototype.guiChanged = function() {\n    this.lx = this.x;\n    this.ly = this.y;\n    this.lz = this.z;\n    this.o = this.go;\n    this.lo = this.go;\n    return this.lp = this.p;\n  };\n\n  FlyCam.prototype.guiUpdate = function() {\n    this.go = this.o % 360;\n    this.xgui.updateDisplay();\n    this.ygui.updateDisplay();\n    this.zgui.updateDisplay();\n    this.ogui.updateDisplay();\n    return this.pgui.updateDisplay();\n  };\n\n  FlyCam.prototype.accelerate = function() {\n    var ax, ay, az, ctrl_x, ctrl_y, ctrl_z, sl, sr;\n    sl = this.delta * this.delta * this.sl;\n    sr = this.delta * this.delta * this.sr;\n    ctrl_x = keys.a ? -1 : keys.d ? 1 : 0;\n    ctrl_y = keys.q ? -1 : keys.e ? 1 : 0;\n    ctrl_z = keys.w ? -1 : keys.s ? 1 : 0;\n    ax = ctrl_x * sl;\n    ay = ctrl_y * sl;\n    az = ctrl_z * sl;\n    this.rot.identity().rotatey(-this.o).rotatex(-this.p).mulVal3(ax, ay, az, this.acc);\n    this.x += this.acc.x;\n    this.y += this.acc.y;\n    this.z += this.acc.z;\n    this.o += this.mouse.x * sr;\n    return this.p += this.mouse.y * sr;\n  };\n\n  FlyCam.prototype.move = function() {\n    var o, p, retl, retr, x, y, z;\n    retl = 0.97;\n    retr = 0.94;\n    x = this.x + (this.x - this.lx) * retl;\n    y = this.y + (this.y - this.ly) * retl;\n    z = this.z + (this.z - this.lz) * retl;\n    o = this.o + (this.o - this.lo) * retr;\n    p = this.p + (this.p - this.lp) * retr;\n    if (p > 80) {\n      p = 80;\n    } else if (p < -80) {\n      p = -80;\n    }\n    this.lx = this.x;\n    this.x = x;\n    this.ly = this.y;\n    this.y = y;\n    this.lz = this.z;\n    this.z = z;\n    this.lo = this.o;\n    this.o = o;\n    this.lp = this.p;\n    return this.p = p;\n  };\n\n  FlyCam.prototype.finish = function() {\n    this.mouse.reset();\n    return this.view.identity().rotatex(this.p).rotatey(this.o).translateVal3(-this.x, -this.y, -this.z);\n  };\n\n  return FlyCam;\n\n})(Camera);\n});\n    \n    loader.define('/webgl-texture-float-extension-shims.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar checkColorBuffer, checkFloatLinear, checkSupport, checkTexture, createSourceCanvas, getExtension, getSupportedExtensions, name, shimExtensions, shimLookup, unshimExtensions, unshimLookup, _i, _len,\n  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\ncreateSourceCanvas = function() {\n  var canvas, ctx, imageData;\n  canvas = document.createElement('canvas');\n  canvas.width = 2;\n  canvas.height = 2;\n  ctx = canvas.getContext('2d');\n  imageData = ctx.getImageData(0, 0, 2, 2);\n  imageData.data.set(new Uint8ClampedArray([0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255]));\n  ctx.putImageData(imageData, 0, 0);\n  return canvas;\n};\n\ncreateSourceCanvas();\n\ncheckFloatLinear = function(gl, sourceType) {\n  var buffer, cleanup, fragmentShader, framebuffer, positionLoc, program, readBuffer, result, source, sourceCanvas, sourceLoc, target, vertexShader, vertices;\n  program = gl.createProgram();\n  vertexShader = gl.createShader(gl.VERTEX_SHADER);\n  gl.attachShader(program, vertexShader);\n  gl.shaderSource(vertexShader, 'attribute vec2 position;\\nvoid main(){\\n    gl_Position = vec4(position, 0.0, 1.0);\\n}');\n  gl.compileShader(vertexShader);\n  if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n    throw gl.getShaderInfoLog(vertexShader);\n  }\n  fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n  gl.attachShader(program, fragmentShader);\n  gl.shaderSource(fragmentShader, 'uniform sampler2D source;\\nvoid main(){\\n    gl_FragColor = texture2D(source, vec2(1.0, 1.0));\\n}');\n  gl.compileShader(fragmentShader);\n  if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n    throw gl.getShaderInfoLog(fragmentShader);\n  }\n  gl.linkProgram(program);\n  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n    throw gl.getProgramInfoLog(program);\n  }\n  gl.useProgram(program);\n  cleanup = function() {\n    gl.deleteShader(fragmentShader);\n    gl.deleteShader(vertexShader);\n    gl.deleteProgram(program);\n    gl.deleteBuffer(buffer);\n    gl.deleteTexture(source);\n    gl.deleteTexture(target);\n    gl.deleteFramebuffer(framebuffer);\n    gl.bindBuffer(gl.ARRAY_BUFFER, null);\n    gl.useProgram(null);\n    gl.bindTexture(gl.TEXTURE_2D, null);\n    return gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n  };\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n  framebuffer = gl.createFramebuffer();\n  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);\n  sourceCanvas = createSourceCanvas();\n  source = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, source);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, sourceType, sourceCanvas);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n  vertices = new Float32Array([1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1]);\n  buffer = gl.createBuffer();\n  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);\n  positionLoc = gl.getAttribLocation(program, 'position');\n  sourceLoc = gl.getUniformLocation(program, 'source');\n  gl.enableVertexAttribArray(positionLoc);\n  gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);\n  gl.uniform1i(sourceLoc, 0);\n  gl.drawArrays(gl.TRIANGLES, 0, 6);\n  readBuffer = new Uint8Array(4 * 4);\n  gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, readBuffer);\n  result = Math.abs(readBuffer[0] - 127) < 10;\n  cleanup();\n  return result;\n};\n\ncheckTexture = function(gl, targetType) {\n  var target;\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, targetType, null);\n  if (gl.getError() === 0) {\n    gl.deleteTexture(target);\n    return true;\n  } else {\n    gl.deleteTexture(target);\n    return false;\n  }\n};\n\ncheckColorBuffer = function(gl, targetType) {\n  var check, framebuffer, target;\n  target = gl.createTexture();\n  gl.bindTexture(gl.TEXTURE_2D, target);\n  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, targetType, null);\n  framebuffer = gl.createFramebuffer();\n  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, target, 0);\n  check = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n  gl.deleteTexture(target);\n  gl.deleteFramebuffer(framebuffer);\n  gl.bindTexture(gl.TEXTURE_2D, null);\n  gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n  if (check === gl.FRAMEBUFFER_COMPLETE) {\n    return true;\n  } else {\n    return false;\n  }\n};\n\nshimExtensions = [];\n\nshimLookup = {};\n\nunshimExtensions = [];\n\ncheckSupport = function() {\n  var canvas, extobj, gl, halfFloatExt, halfFloatTexturing, singleFloatExt, singleFloatTexturing;\n  canvas = document.createElement('canvas');\n  gl = null;\n  try {\n    gl = canvas.getContext('experimental-webgl');\n    if (gl === null) {\n      gl = canvas.getContext('webgl');\n    }\n  } catch (_error) {}\n  if (gl != null) {\n    singleFloatExt = gl.getExtension('OES_texture_float');\n    if (singleFloatExt === null) {\n      if (checkTexture(gl, gl.FLOAT)) {\n        singleFloatTexturing = true;\n        shimExtensions.push('OES_texture_float');\n        shimLookup.OES_texture_float = {\n          shim: true\n        };\n      } else {\n        singleFloatTexturing = false;\n        unshimExtensions.push('OES_texture_float');\n      }\n    } else {\n      if (checkTexture(gl, gl.FLOAT)) {\n        singleFloatTexturing = true;\n        shimExtensions.push('OES_texture_float');\n      } else {\n        singleFloatTexturing = false;\n        unshimExtensions.push('OES_texture_float');\n      }\n    }\n    if (singleFloatTexturing) {\n      extobj = gl.getExtension('WEBGL_color_buffer_float');\n      if (extobj === null) {\n        if (checkColorBuffer(gl, gl.FLOAT)) {\n          shimExtensions.push('WEBGL_color_buffer_float');\n          shimLookup.WEBGL_color_buffer_float = {\n            shim: true,\n            RGBA32F_EXT: 0x8814,\n            RGB32F_EXT: 0x8815,\n            FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211,\n            UNSIGNED_NORMALIZED_EXT: 0x8C17\n          };\n        } else {\n          unshimExtensions.push('WEBGL_color_buffer_float');\n        }\n      } else {\n        if (checkColorBuffer(gl, gl.FLOAT)) {\n          shimExtensions.push('WEBGL_color_buffer_float');\n        } else {\n          unshimExtensions.push('WEBGL_color_buffer_float');\n        }\n      }\n      extobj = gl.getExtension('OES_texture_float_linear');\n      if (extobj === null) {\n        if (checkFloatLinear(gl, gl.FLOAT)) {\n          shimExtensions.push('OES_texture_float_linear');\n          shimLookup.OES_texture_float_linear = {\n            shim: true\n          };\n        } else {\n          unshimExtensions.push('OES_texture_float_linear');\n        }\n      } else {\n        if (checkFloatLinear(gl, gl.FLOAT)) {\n          shimExtensions.push('OES_texture_float_linear');\n        } else {\n          unshimExtensions.push('OES_texture_float_linear');\n        }\n      }\n    }\n    halfFloatExt = gl.getExtension('OES_texture_half_float');\n    if (halfFloatExt === null) {\n      if (checkTexture(gl, 0x8D61)) {\n        halfFloatTexturing = true;\n        shimExtensions.push('OES_texture_half_float');\n        halfFloatExt = shimLookup.OES_texture_half_float = {\n          HALF_FLOAT_OES: 0x8D61,\n          shim: true\n        };\n      } else {\n        halfFloatTexturing = false;\n        unshimExtensions.push('OES_texture_half_float');\n      }\n    } else {\n      if (checkTexture(gl, halfFloatExt.HALF_FLOAT_OES)) {\n        halfFloatTexturing = true;\n        shimExtensions.push('OES_texture_half_float');\n      } else {\n        halfFloatTexturing = false;\n        unshimExtensions.push('OES_texture_half_float');\n      }\n    }\n    if (halfFloatTexturing) {\n      extobj = gl.getExtension('EXT_color_buffer_half_float');\n      if (extobj === null) {\n        if (checkColorBuffer(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('EXT_color_buffer_half_float');\n          shimLookup.EXT_color_buffer_half_float = {\n            shim: true,\n            RGBA16F_EXT: 0x881A,\n            RGB16F_EXT: 0x881B,\n            FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0x8211,\n            UNSIGNED_NORMALIZED_EXT: 0x8C17\n          };\n        } else {\n          unshimExtensions.push('EXT_color_buffer_half_float');\n        }\n      } else {\n        if (checkColorBuffer(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('EXT_color_buffer_half_float');\n        } else {\n          unshimExtensions.push('EXT_color_buffer_half_float');\n        }\n      }\n      extobj = gl.getExtension('OES_texture_half_float_linear');\n      if (extobj === null) {\n        if (checkFloatLinear(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          shimExtensions.push('OES_texture_half_float_linear');\n          return shimLookup.OES_texture_half_float_linear = {\n            shim: true\n          };\n        } else {\n          return unshimExtensions.push('OES_texture_half_float_linear');\n        }\n      } else {\n        if (checkFloatLinear(gl, halfFloatExt.HALF_FLOAT_OES)) {\n          return shimExtensions.push('OES_texture_half_float_linear');\n        } else {\n          return unshimExtensions.push('OES_texture_half_float_linear');\n        }\n      }\n    }\n  }\n};\n\nif (window.WebGLRenderingContext != null) {\n  checkSupport();\n  unshimLookup = {};\n  for (_i = 0, _len = unshimExtensions.length; _i < _len; _i++) {\n    name = unshimExtensions[_i];\n    unshimLookup[name] = true;\n  }\n  getExtension = WebGLRenderingContext.prototype.getExtension;\n  WebGLRenderingContext.prototype.getExtension = function(name) {\n    var extobj;\n    extobj = shimLookup[name];\n    if (extobj === void 0) {\n      if (unshimLookup[name]) {\n        return null;\n      } else {\n        return getExtension.call(this, name);\n      }\n    } else {\n      return extobj;\n    }\n  };\n  getSupportedExtensions = WebGLRenderingContext.prototype.getSupportedExtensions;\n  WebGLRenderingContext.prototype.getSupportedExtensions = function() {\n    var extension, result, supported, _j, _k, _len1, _len2;\n    supported = getSupportedExtensions.call(this);\n    result = [];\n    for (_j = 0, _len1 = supported.length; _j < _len1; _j++) {\n      extension = supported[_j];\n      if (unshimLookup[extension] === void 0) {\n        result.push(extension);\n      }\n    }\n    for (_k = 0, _len2 = shimExtensions.length; _k < _len2; _k++) {\n      extension = shimExtensions[_k];\n      if (__indexOf.call(result, extension) < 0) {\n        result.push(extension);\n      }\n    }\n    return result;\n  };\n  WebGLRenderingContext.prototype.getFloatExtension = function(spec) {\n    var candidate, candidates, half, halfFramebuffer, halfLinear, halfTexture, i, importance, preference, result, single, singleFramebuffer, singleLinear, singleTexture, use, _j, _k, _l, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;\n    if ((_ref = spec.prefer) == null) {\n      spec.prefer = ['half'];\n    }\n    if ((_ref1 = spec.require) == null) {\n      spec.require = [];\n    }\n    if ((_ref2 = spec.throws) == null) {\n      spec.throws = true;\n    }\n    singleTexture = this.getExtension('OES_texture_float');\n    halfTexture = this.getExtension('OES_texture_half_float');\n    singleFramebuffer = this.getExtension('WEBGL_color_buffer_float');\n    halfFramebuffer = this.getExtension('EXT_color_buffer_half_float');\n    singleLinear = this.getExtension('OES_texture_float_linear');\n    halfLinear = this.getExtension('OES_texture_half_float_linear');\n    single = {\n      texture: singleTexture !== null,\n      filterable: singleLinear !== null,\n      renderable: singleFramebuffer !== null,\n      score: 0,\n      precision: 'single',\n      half: false,\n      single: true,\n      type: this.FLOAT\n    };\n    half = {\n      texture: halfTexture !== null,\n      filterable: halfLinear !== null,\n      renderable: halfFramebuffer !== null,\n      score: 0,\n      precision: 'half',\n      half: true,\n      single: false,\n      type: (_ref3 = halfTexture != null ? halfTexture.HALF_FLOAT_OES : void 0) != null ? _ref3 : null\n    };\n    candidates = [];\n    if (single.texture) {\n      candidates.push(single);\n    }\n    if (half.texture) {\n      candidates.push(half);\n    }\n    result = [];\n    for (_j = 0, _len1 = candidates.length; _j < _len1; _j++) {\n      candidate = candidates[_j];\n      use = true;\n      _ref4 = spec.require;\n      for (_k = 0, _len2 = _ref4.length; _k < _len2; _k++) {\n        name = _ref4[_k];\n        if (candidate[name] === false) {\n          use = false;\n        }\n      }\n      if (use) {\n        result.push(candidate);\n      }\n    }\n    for (_l = 0, _len3 = result.length; _l < _len3; _l++) {\n      candidate = result[_l];\n      _ref5 = spec.prefer;\n      for (i = _m = 0, _len4 = _ref5.length; _m < _len4; i = ++_m) {\n        preference = _ref5[i];\n        importance = Math.pow(2, spec.prefer.length - i - 1);\n        if (candidate[preference]) {\n          candidate.score += importance;\n        }\n      }\n    }\n    result.sort(function(a, b) {\n      if (a.score === b.score) {\n        return 0;\n      } else if (a.score < b.score) {\n        return 1;\n      } else if (a.score > b.score) {\n        return -1;\n      }\n    });\n    if (result.length === 0) {\n      if (spec.throws) {\n        throw 'No floating point texture support that is ' + spec.require.join(', ');\n      } else {\n        return null;\n      }\n    } else {\n      result = result[0];\n      return {\n        filterable: result.filterable,\n        renderable: result.renderable,\n        type: result.type,\n        precision: result.precision\n      };\n    }\n  };\n}\n});\n    \n    loader.define('/audio.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Backend, HTMLAudio, WebAudio, backend,\n  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nBackend = (function() {\n\n  function Backend() {\n    this.loading = 0;\n    this.handlers = [];\n  }\n\n  Backend.prototype.loaded = function() {\n    var handler, _i, _len, _ref;\n    if (this.loading === 0) {\n      _ref = this.handlers;\n      for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n        handler = _ref[_i];\n        if (handler.event === 'loaded') {\n          handler.callback.apply(handler);\n        }\n      }\n    }\n  };\n\n  Backend.prototype.bind = function(event, callback) {\n    var handler;\n    handler = {\n      event: event,\n      callback: callback\n    };\n    this.handlers.push(handler);\n    return handler;\n  };\n\n  Backend.prototype.unbind = function(handler) {\n    var index;\n    index = this.handlers.indexOf(handler);\n    if (index >= 0) {\n      return this.handlers.splice(index, 1);\n    }\n  };\n\n  return Backend;\n\n})();\n\nHTMLAudio = (function(_super) {\n  var Sample, Voice;\n\n  __extends(HTMLAudio, _super);\n\n  HTMLAudio.available = (window.Audio !== void 0) && (window.URL !== void 0) && (window.BlobBuilder !== void 0);\n\n  Sample = (function() {\n\n    function Sample(backend, data) {\n      this.backend = backend;\n      this.backend.loading += 1;\n      this.url = blob.pack(data, 'audio/ogg');\n    }\n\n    Sample.prototype.play = function(looping) {\n      var voice;\n      voice = this.backend.getFree();\n      if (voice) {\n        return voice.play(this.url, looping);\n      }\n    };\n\n    return Sample;\n\n  })();\n\n  Voice = (function() {\n\n    function Voice(backend, id) {\n      var self;\n      this.id = id;\n      self = this;\n      this.audio = new Audio();\n      this.audio.onended = function() {\n        return backend.ended(self);\n      };\n    }\n\n    Voice.prototype.play = function(url) {\n      this.audio.src = url;\n      return this.audio.play();\n    };\n\n    return Voice;\n\n  })();\n\n  function HTMLAudio() {\n    this.check = __bind(this.check, this);\n\n    var id, _i;\n    this.free = {};\n    this.playing = {};\n    for (id = _i = 0; _i < 20; id = ++_i) {\n      this.free[id] = new Voice(this, id);\n    }\n    setInterval(this.check, 100);\n  }\n\n  HTMLAudio.prototype.check = function() {};\n\n  HTMLAudio.prototype.getFree = function() {\n    var id, voice, _ref;\n    _ref = this.free;\n    for (id in _ref) {\n      voice = _ref[id];\n      delete this.free[id];\n      this.playing[id] = voice;\n      return voice;\n    }\n  };\n\n  HTMLAudio.prototype.ended = function(voice) {\n    this.free[voice.id] = voice;\n    return delete this.playing[voice.id];\n  };\n\n  HTMLAudio.prototype.createSample = function(data) {\n    this.start_time = gettime();\n    return new Sample(this, data);\n  };\n\n  return HTMLAudio;\n\n})(Backend);\n\nWebAudio = (function(_super) {\n\n  __extends(WebAudio, _super);\n\n  WebAudio.available = window.webkitAudioContext !== void 0;\n\n  function WebAudio() {\n    WebAudio.__super__.constructor.call(this);\n    this.ctx = new webkitAudioContext();\n  }\n\n  WebAudio.prototype.play = function(buffer, looping) {\n    var source;\n    if (looping == null) {\n      looping = false;\n    }\n    source = this.ctx.createBufferSource();\n    source.buffer = buffer;\n    source.loop = looping;\n    source.connect(this.ctx.destination);\n    return source.noteOn(this.ctx.currentTime);\n  };\n\n  WebAudio.prototype.decode = function(data, callback) {\n    return this.ctx.decodeAudioData(data, function(buffer) {\n      return callback(buffer);\n    });\n  };\n\n  return WebAudio;\n\n})(Backend);\n\nif (WebAudio.available) {\n  backend = new WebAudio();\n  exports.decode = function(data, callback) {\n    return backend.decode(data, callback);\n  };\n  exports.play = function(buffer) {\n    return backend.play(buffer);\n  };\n} else {\n  exports.decode = function(data, callback) {};\n  exports.play = function(buffer) {};\n}\n});\n    \n    loader.define('/events.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Emitter;\n\nreturn Emitter = (function() {\n\n  function Emitter() {\n    this.handlers = {};\n  }\n\n  Emitter.prototype.on = function(name, callback) {\n    var handlers;\n    handlers = this.handlers[name];\n    if (handlers === void 0) {\n      handlers = this.handlers[name] = [];\n    }\n    handlers.push(callback);\n    return this;\n  };\n\n  Emitter.prototype.trigger = function(name, a1, a2, a3, a4, a5, a6) {\n    var handler, handlers, _i, _len;\n    handlers = this.handlers[name];\n    if (handlers !== void 0) {\n      for (_i = 0, _len = handlers.length; _i < _len; _i++) {\n        handler = handlers[_i];\n        handler(a1, a2, a3, a4, a5, a6);\n      }\n    }\n    return this;\n  };\n\n  return Emitter;\n\n})();\n});\n    \n    loader.define('/rendernode.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Cubemap, Depthbuffer, Framebuffer, Quad, Rendernode, State, Texture2D, default_state, _ref, _ref1;\n\n_ref = require('webgl/framebuffer'), Framebuffer = _ref.Framebuffer, Depthbuffer = _ref.Depthbuffer;\n\n_ref1 = require('webgl/texture'), Texture2D = _ref1.Texture2D, Cubemap = _ref1.Cubemap;\n\nQuad = require('webgl/quad');\n\nState = (function() {\n\n  function State(gl) {\n    this.gl = gl;\n    this.depthTest = false;\n    this.depthWrite = false;\n    this.cullFace = null;\n    this.alphaToCoverage = false;\n    this.blend = false;\n  }\n\n  State.prototype.setDefaults = function() {\n    this.gl.disable(this.gl.DEPTH_TEST);\n    this.gl.depthMask(false);\n    this.gl.cullFace(this.gl.BACK);\n    this.gl.disable(this.gl.CULL_FACE);\n    this.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    this.gl.disable(this.gl.BLEND);\n    return this;\n  };\n\n  State.prototype.set = function() {\n    var mode;\n    if (this.depthTest) {\n      this.gl.enable(this.gl.DEPTH_TEST);\n      mode = this.gl[this.depthTest];\n      if (mode) {\n        this.gl.depthFunc(mode);\n      } else {\n        this.gl.depthFunc(this.gl.LEQUAL);\n      }\n    }\n    if (this.depthWrite) {\n      this.gl.depthMask(true);\n    }\n    if (this.cullFace) {\n      this.gl.enable(this.gl.CULL_FACE);\n      this.gl.cullFace(this.gl[this.cullFace]);\n    }\n    if (this.blend) {\n      this.gl.enable(this.gl.BLEND);\n      if (this.blend === 'additive') {\n        this.gl.blendFunc(this.gl.ONE, this.gl.ONE);\n      }\n    }\n    if (this.alphaToCoverage) {\n      this.gl.enable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    }\n    return this;\n  };\n\n  State.prototype.revert = function() {\n    if (this.depthTest) {\n      this.gl.disable(this.gl.DEPTH_TEST);\n      this.gl.depthFunc(this.gl.LESS);\n    }\n    if (this.depthWrite) {\n      this.gl.depthMask(false);\n    }\n    if (this.cullFace) {\n      this.gl.disable(this.gl.CULL_FACE);\n    }\n    if (this.blend) {\n      this.gl.disable(this.gl.BLEND);\n    }\n    if (this.alphaToCoverage) {\n      this.gl.disable(this.gl.SAMPLE_ALPHA_TO_COVERAGE);\n    }\n    return this;\n  };\n\n  return State;\n\n})();\n\ndefault_state = null;\n\nreturn Rendernode = (function() {\n\n  Rendernode.stateDefaults = function(gl) {\n    return default_state = new State(gl).setDefaults();\n  };\n\n  function Rendernode(gl, _arg) {\n    var blend, cullFace, depthTest, depthWrite, _ref2, _ref3;\n    this.gl = gl;\n    this.width = _arg.width, this.height = _arg.height, this.program = _arg.program, this.drawable = _arg.drawable, this.type = _arg.type, this.front = _arg.front, depthTest = _arg.depthTest, depthWrite = _arg.depthWrite, cullFace = _arg.cullFace, this.depthBuffer = _arg.depthBuffer, blend = _arg.blend, this.filter = _arg.filter, this.channels = _arg.channels, this.format = _arg.format, this.hdrClear = _arg.hdrClear;\n    this.xoff = 0;\n    this.yoff = 0;\n    this.state = new State(this.gl);\n    this.texunit_counter = 0;\n    this.texunits = {};\n    if ((_ref2 = this.type) == null) {\n      this.type = this.gl.UNSIGNED_BYTE;\n    }\n    if ((_ref3 = this.front) == null) {\n      this.front = false;\n    }\n    if (depthTest == null) {\n      depthTest = false;\n    }\n    this.depthTest(depthTest);\n    if (depthWrite == null) {\n      depthWrite = false;\n    }\n    this.depthWrite(depthWrite);\n    if (cullFace == null) {\n      cullFace = null;\n    }\n    this.cullFace(cullFace);\n    if (blend == null) {\n      blend = false;\n    }\n    this.state.blend = blend;\n    if (!this.front) {\n      this.createBuffers();\n    }\n    if (this.hdrClear) {\n      this.clearShader = get('hdr_clear.shader');\n    }\n  }\n\n  Rendernode.prototype.createBuffers = function() {\n    this.output = new Texture2D(this.gl, {\n      channels: this.channels,\n      format: this.format,\n      type: this.type\n    }).bind().clampToEdge();\n    if (this.filter === 'nearest') {\n      this.output.nearest();\n    } else {\n      this.output.linear();\n    }\n    if (this.width && this.height) {\n      this.output.setSize(this.width, this.height);\n    } else {\n      this.output.setSize(16, 16);\n    }\n    this.output.unbind();\n    this.fbo = new Framebuffer(this.gl).bind().color(this.output).unbind();\n    if (this.depthBuffer) {\n      return this.addDepth();\n    }\n  };\n\n  Rendernode.prototype.addDepth = function(buffer) {\n    if (buffer == null) {\n      buffer = this.depthBuffer;\n    }\n    if (!this.depth && !this.front) {\n      if (buffer instanceof Depthbuffer) {\n        this.depth = buffer;\n      } else {\n        this.depth = new Depthbuffer(this.gl).setSize(this.output.width, this.output.height);\n      }\n      this.fbo.bind().depth(this.depth).unbind();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.cullFace = function(side) {\n    if (side == null) {\n      side = null;\n    }\n    this.state.cullFace = side;\n    return this;\n  };\n\n  Rendernode.prototype.depthWrite = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.depthWrite = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.depthTest = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.depthTest = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.alphaToCoverage = function(enabled) {\n    if (enabled == null) {\n      enabled = false;\n    }\n    this.state.alphaToCoverage = enabled;\n    return this;\n  };\n\n  Rendernode.prototype.blendAdditive = function() {\n    this.state.blend = 'additive';\n    return this;\n  };\n\n  Rendernode.prototype.filterNearest = function() {\n    this.output.bind().nearest().unbind();\n    return this;\n  };\n\n  Rendernode.prototype.start = function() {\n    this.started = true;\n    this.viewport();\n    this.state.set();\n    if (this.program) {\n      this.program.use();\n    }\n    if (!this.front) {\n      this.fbo.bind();\n    }\n    if (this.drawable) {\n      this.setPointers(this.drawable);\n    }\n    return this;\n  };\n\n  Rendernode.prototype.setPointers = function(drawable) {\n    if (drawable !== this.current_drawable) {\n      this.current_drawable = drawable;\n      return drawable.setPointersForShader(this.program);\n    }\n  };\n\n  Rendernode.prototype.end = function() {\n    this.started = false;\n    this.current_drawable = null;\n    this.state.revert();\n    if (!this.front) {\n      this.fbo.unbind();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.sampler = function(name, source) {\n    var texture, unit;\n    if (source.output) {\n      texture = source.output;\n    } else {\n      texture = source;\n    }\n    unit = this.texunits[name];\n    if (unit === void 0) {\n      unit = this.texunits[name] = this.texunit_counter++;\n    }\n    texture.bind(unit);\n    this.program.i(name, unit);\n    return this;\n  };\n\n  Rendernode.prototype.mat4 = function(name, value) {\n    this.program.mat4(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.mat3 = function(name, value) {\n    this.program.mat3(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.val3 = function(name, x, y, z) {\n    this.program.val3(name, x, y, z);\n    return this;\n  };\n\n  Rendernode.prototype.vec3 = function(name, value) {\n    this.program.vec3(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.f = function(name, value) {\n    this.program.f(name, value);\n    return this;\n  };\n\n  Rendernode.prototype.fv = function(name, values) {\n    this.program.fv(name, values);\n    return this;\n  };\n\n  Rendernode.prototype.val2 = function(name, x, y) {\n    this.program.val2(name, x, y);\n    return this;\n  };\n\n  Rendernode.prototype.clear = function(r, g, b, a) {\n    if (r == null) {\n      r = 0;\n    }\n    if (g == null) {\n      g = 0;\n    }\n    if (b == null) {\n      b = 0;\n    }\n    if (a == null) {\n      a = 1;\n    }\n    if (this.hdrClear) {\n      if (!this.front) {\n        this.fbo.bind();\n      }\n      this.clearShader.use().val4('clear_color', r, g, b, a).draw(quad);\n    } else {\n      this.gl.clearColor(r, g, b, a);\n      this.gl.clear(this.gl.COLOR_BUFFER_BIT);\n    }\n    return this;\n  };\n\n  Rendernode.prototype.clearBoth = function(r, g, b, a, depth) {\n    if (r == null) {\n      r = 0;\n    }\n    if (g == null) {\n      g = 0;\n    }\n    if (b == null) {\n      b = 0;\n    }\n    if (a == null) {\n      a = 1;\n    }\n    if (depth == null) {\n      depth = 1;\n    }\n    this.gl.clearColor(r, g, b, a);\n    this.gl.clearDepth(depth);\n    this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n    return this;\n  };\n\n  Rendernode.prototype.clearDepth = function(depth) {\n    if (depth == null) {\n      depth = 1;\n    }\n    this.gl.clearDepth(depth);\n    this.gl.clear(this.gl.DEPTH_BUFFER_BIT);\n    return this;\n  };\n\n  Rendernode.prototype.draw = function(drawable) {\n    var do_end;\n    if (drawable == null) {\n      drawable = this.drawable;\n    }\n    do_end = false;\n    if (!this.started) {\n      do_end = true;\n      this.start();\n    }\n    this.program.val2('viewport', this.width, this.height);\n    if (drawable !== this.current_drawable) {\n      this.setPointers(drawable);\n    }\n    drawable.draw();\n    if (do_end) {\n      this.end();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.drawModel = function(texture_type, sampler_name) {\n    var c, material, _i, _len, _ref2;\n    if (sampler_name == null) {\n      sampler_name = texture_type;\n    }\n    if (texture_type) {\n      _ref2 = this.drawable.materials[texture_type];\n      for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n        material = _ref2[_i];\n        this.f('specularity', material.specularity);\n        c = material.diffuse_color;\n        this.val3('diffuse_color', c.r, c.g, c.b);\n        this.sampler(sampler_name, material[texture_type]);\n        this.drawable.drawRange(material.start, material.size);\n      }\n    } else {\n      this.draw();\n    }\n    return this;\n  };\n\n  Rendernode.prototype.resize = function(width, height) {\n    this.width = Math.floor(width);\n    this.height = Math.floor(height);\n    if (this.output) {\n      this.output.bind().setSize(this.width, this.height).unbind();\n    }\n    if (this.depth) {\n      this.depth.setSize(this.width, this.height);\n    }\n    if (this.fbo) {\n      return this.fbo.bind().check().unbind();\n    }\n  };\n\n  Rendernode.prototype.viewport = function(x, y, width, height) {\n    if (x == null) {\n      x = this.xoff;\n    }\n    if (y == null) {\n      y = this.yoff;\n    }\n    if (width == null) {\n      width = this.width;\n    }\n    if (height == null) {\n      height = this.height;\n    }\n    if (width && height) {\n      this.xoff = x;\n      this.yoff = y;\n      this.width = width;\n      this.height = height;\n      if (this.started) {\n        this.gl.viewport(x, y, width, height);\n      }\n      return this;\n    }\n  };\n\n  Rendernode.prototype.bind = function(unit) {\n    if (unit == null) {\n      unit = 0;\n    }\n    return this.output.bind(unit);\n  };\n\n  return Rendernode;\n\n})();\n});\n    \n    loader.define('/schedule.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\n\nexports.run = function(callback) {\n  var last, step;\n  last = gettime();\n  step = function() {\n    var current, delta;\n    current = gettime();\n    delta = current - last;\n    last = current;\n    callback(current, delta);\n    return requestAnimationFrame(step);\n  };\n  return requestAnimationFrame(step);\n};\n});\n    \n    loader.define('/webgl/plane.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Plane,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Plane = (function(_super) {\n\n  __extends(Plane, _super);\n\n  Plane.prototype.attribs = ['position', 'normal', 'texcoord'];\n\n  function Plane(gl, s) {\n    var vertices;\n    this.gl = gl;\n    if (s == null) {\n      s = 1;\n    }\n    Plane.__super__.constructor.call(this);\n    this.size = 6;\n    vertices = [-s, 0, -s, 0, 1, 0, 0, 0, -s, 0, s, 0, 1, 0, 0, 1, s, 0, s, 0, 1, 0, 1, 1, s, 0, -s, 0, 1, 0, 1, 0, -s, 0, -s, 0, 1, 0, 0, 0, s, 0, s, 0, 1, 0, 1, 1];\n    this.uploadList(vertices);\n  }\n\n  Plane.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'normal', 3, 3, 8);\n    this.setPointer(shader, 'texcoord', 2, 6, 8);\n    return this;\n  };\n\n  return Plane;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/model.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Model,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Model = (function(_super) {\n\n  __extends(Model, _super);\n\n  Model.prototype.attribs = ['position', 'normal', 'texcoord'];\n\n  function Model(gl, data) {\n    this.gl = gl;\n    Model.__super__.constructor.call(this);\n    this.size = data.byteLength / (8 * Float32Array.BYTES_PER_ELEMENT);\n    this.upload(data);\n  }\n\n  Model.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'normal', 3, 3, 8);\n    this.setPointer(shader, 'texcoord', 2, 6, 8);\n    return this;\n  };\n\n  return Model;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/cube.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Cube,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Cube = (function(_super) {\n\n  __extends(Cube, _super);\n\n  Cube.prototype.attribs = ['position', 'normal', 'barycentric'];\n\n  Cube.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 9\n    }, {\n      name: 'normal',\n      size: 3,\n      offset: 3,\n      stride: 9\n    }, {\n      name: 'barycentric',\n      size: 3,\n      offset: 6,\n      stride: 9\n    }\n  ];\n\n  function Cube(gl, s) {\n    var vertices;\n    this.gl = gl;\n    if (s == null) {\n      s = 1;\n    }\n    Cube.__super__.constructor.call(this);\n    this.size = 6 * 6;\n    vertices = [-s, -s, -s, 0, 0, -1, 1, 0, 0, -s, s, -s, 0, 0, -1, 0, 1, 0, s, s, -s, 0, 0, -1, 0, 0, 1, s, -s, -s, 0, 0, -1, 1, 0, 0, -s, -s, -s, 0, 0, -1, 0, 1, 0, s, s, -s, 0, 0, -1, 0, 0, 1, s, s, s, 0, 0, 1, 1, 0, 0, -s, s, s, 0, 0, 1, 0, 1, 0, -s, -s, s, 0, 0, 1, 0, 0, 1, s, s, s, 0, 0, 1, 1, 0, 0, -s, -s, s, 0, 0, 1, 0, 1, 0, s, -s, s, 0, 0, 1, 0, 0, 1, -s, s, -s, 0, 1, 0, 1, 0, 0, -s, s, s, 0, 1, 0, 0, 1, 0, s, s, s, 0, 1, 0, 0, 0, 1, s, s, -s, 0, 1, 0, 1, 0, 0, -s, s, -s, 0, 1, 0, 0, 1, 0, s, s, s, 0, 1, 0, 0, 0, 1, s, -s, s, 0, -1, 0, 1, 0, 0, -s, -s, s, 0, -1, 0, 0, 1, 0, -s, -s, -s, 0, -1, 0, 0, 0, 1, s, -s, s, 0, -1, 0, 1, 0, 0, -s, -s, -s, 0, -1, 0, 0, 1, 0, s, -s, -s, 0, -1, 0, 0, 0, 1, -s, -s, -s, -1, 0, 0, 1, 0, 0, -s, -s, s, -1, 0, 0, 0, 1, 0, -s, s, s, -1, 0, 0, 0, 0, 1, -s, s, -s, -1, 0, 0, 1, 0, 0, -s, -s, -s, -1, 0, 0, 0, 1, 0, -s, s, s, -1, 0, 0, 0, 0, 1, s, s, s, 1, 0, 0, 1, 0, 0, s, -s, s, 1, 0, 0, 0, 1, 0, s, -s, -s, 1, 0, 0, 0, 0, 1, s, s, s, 1, 0, 0, 1, 0, 0, s, -s, -s, 1, 0, 0, 0, 1, 0, s, s, -s, 1, 0, 0, 0, 0, 1];\n    this.uploadList(vertices);\n  }\n\n  return Cube;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/framebuffer.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Framebuffer, Renderbuffer, framebufferBinding,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nframebufferBinding = null;\n\nexports.Framebuffer = Framebuffer = (function() {\n\n  function Framebuffer(gl) {\n    this.gl = gl;\n    this.buffer = this.gl.createFramebuffer();\n  }\n\n  Framebuffer.prototype.bind = function() {\n    if (framebufferBinding !== this) {\n      this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, this.buffer);\n      framebufferBinding = this;\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.unbind = function() {\n    if (framebufferBinding !== null) {\n      this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n      framebufferBinding = null;\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.check = function() {\n    var result;\n    result = this.gl.checkFramebufferStatus(this.gl.FRAMEBUFFER);\n    switch (result) {\n      case this.gl.FRAMEBUFFER_UNSUPPORTED:\n        throw 'Framebuffer is unsupported';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:\n        throw 'Framebuffer incomplete attachment';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:\n        throw 'Framebuffer incomplete dimensions';\n        break;\n      case this.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:\n        throw 'Framebuffer incomplete missing attachment';\n    }\n    return this;\n  };\n\n  Framebuffer.prototype.color = function(texture, target) {\n    if (target == null) {\n      target = texture.target;\n    }\n    this.gl.framebufferTexture2D(this.gl.FRAMEBUFFER, this.gl.COLOR_ATTACHMENT0, target, texture.handle, 0);\n    this.check();\n    return this;\n  };\n\n  Framebuffer.prototype.depth = function(buffer) {\n    this.gl.framebufferRenderbuffer(this.gl.FRAMEBUFFER, this.gl.DEPTH_ATTACHMENT, this.gl.RENDERBUFFER, buffer.id);\n    this.check();\n    return this;\n  };\n\n  Framebuffer.prototype.destroy = function() {\n    return this.gl.deleteFramebuffer(this.buffer);\n  };\n\n  return Framebuffer;\n\n})();\n\nRenderbuffer = (function() {\n\n  function Renderbuffer(gl) {\n    this.gl = gl;\n    this.id = this.gl.createRenderbuffer();\n  }\n\n  Renderbuffer.prototype.bind = function() {\n    this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.id);\n    return this;\n  };\n\n  Renderbuffer.prototype.setSize = function(width, height) {\n    this.width = width;\n    this.height = height;\n    this.bind();\n    this.gl.renderbufferStorage(this.gl.RENDERBUFFER, this.gl[this.format], this.width, this.height);\n    return this.unbind();\n  };\n\n  Renderbuffer.prototype.unbind = function() {\n    this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);\n    return this;\n  };\n\n  return Renderbuffer;\n\n})();\n\nexports.Depthbuffer = (function(_super) {\n\n  __extends(_Class, _super);\n\n  function _Class() {\n    return _Class.__super__.constructor.apply(this, arguments);\n  }\n\n  _Class.prototype.format = 'DEPTH_COMPONENT16';\n\n  return _Class;\n\n})(Renderbuffer);\n});\n    \n    loader.define('/webgl/quad.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Quad,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nreturn Quad = (function(_super) {\n\n  __extends(Quad, _super);\n\n  Quad.prototype.attribs = ['position'];\n\n  Quad.prototype.pointers = [\n    {\n      name: 'position',\n      size: 2,\n      offset: 0,\n      stride: 2\n    }\n  ];\n\n  function Quad(gl) {\n    var vertices;\n    this.gl = gl;\n    Quad.__super__.constructor.call(this);\n    this.size = 6;\n    vertices = [-1, -1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1];\n    this.uploadList(vertices);\n  }\n\n  return Quad;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/hexgrid.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Hexgrid, clamp,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nclamp = function(value, left, right) {\n  if (value < left) {\n    return left;\n  } else if (value > right) {\n    return right;\n  } else {\n    return value;\n  }\n};\n\nreturn Hexgrid = (function(_super) {\n\n  __extends(Hexgrid, _super);\n\n  Hexgrid.prototype.attribs = ['position', 'texcoord', 'barycentric'];\n\n  function Hexgrid(gl, xsize, ysize, width, height) {\n    var b, m, t, vertices, x, x1, x2, x3, x4, y, _i, _j;\n    this.gl = gl;\n    if (xsize == null) {\n      xsize = 16;\n    }\n    if (ysize == null) {\n      ysize = 16;\n    }\n    if (width == null) {\n      width = 1;\n    }\n    if (height == null) {\n      height = 1;\n    }\n    Hexgrid.__super__.constructor.call(this);\n    vertices = [];\n    for (x = _i = 0; 0 <= xsize ? _i <= xsize : _i >= xsize; x = 0 <= xsize ? ++_i : --_i) {\n      x1 = clamp((x - 0.5) / xsize, 0, 1);\n      x2 = clamp((x + 0.0) / xsize, 0, 1);\n      x3 = clamp((x + 0.5) / xsize, 0, 1);\n      x4 = clamp((x + 1.0) / xsize, 0, 1);\n      for (y = _j = 0; _j < ysize; y = _j += 2) {\n        t = (y + 0) / ysize;\n        m = (y + 1) / ysize;\n        b = (y + 2) / ysize;\n        vertices.push(x2 * width, 0, m * height, x2, m, 0, 0, 1, x3 * width, 0, t * height, x3, t, 0, 1, 0, x1 * width, 0, t * height, x1, t, 1, 0, 0, x4 * width, 0, m * height, x4, m, 0, 0, 1, x3 * width, 0, t * height, x3, t, 0, 1, 0, x2 * width, 0, m * height, x2, m, 1, 0, 0, x3 * width, 0, b * height, x3, b, 0, 0, 1, x2 * width, 0, m * height, x2, m, 0, 1, 0, x1 * width, 0, b * height, x1, b, 1, 0, 0, x3 * width, 0, b * height, x3, b, 0, 0, 1, x4 * width, 0, m * height, x4, m, 0, 1, 0, x2 * width, 0, m * height, x2, m, 1, 0, 0);\n      }\n    }\n    this.size = vertices.length / 8;\n    this.uploadList(vertices);\n  }\n\n  Hexgrid.prototype.setPointersForShader = function(shader) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.setPointer(shader, 'position', 3, 0, 8);\n    this.setPointer(shader, 'texcoord', 2, 3, 8);\n    this.setPointer(shader, 'barycentric', 3, 5, 8);\n    return this;\n  };\n\n  return Hexgrid;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/drawable.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Drawable;\n\nreturn Drawable = (function() {\n  var float_size;\n\n  float_size = Float32Array.BYTES_PER_ELEMENT;\n\n  function Drawable() {\n    this.first = 0;\n    this.size = 0;\n    this.buffer = this.gl.createBuffer();\n    this.mode = this.gl.TRIANGLES;\n  }\n\n  Drawable.prototype.setPointer = function(shader, name, size, start, stride) {\n    var location;\n    if (size == null) {\n      size = 3;\n    }\n    if (start == null) {\n      start = 0;\n    }\n    if (stride == null) {\n      stride = 0;\n    }\n    location = shader.attribLoc(name);\n    if (location >= 0) {\n      this.gl.vertexAttribPointer(location, size, this.gl.FLOAT, false, stride * float_size, start * float_size);\n    }\n    return this;\n  };\n\n  Drawable.prototype.setPointersForShader = function(shader) {\n    var pointer, _i, _len, _ref;\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    _ref = this.pointers;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      pointer = _ref[_i];\n      this.setPointer(shader, pointer.name, pointer.size, pointer.offset, pointer.stride);\n    }\n    return this;\n  };\n\n  Drawable.prototype.draw = function(shader) {\n    if (shader) {\n      this.setPointersForShader(shader);\n    }\n    this.gl.drawArrays(this.mode, this.first, this.size);\n    if (shader) {\n      this.disableAttribs(shader);\n    }\n    return this;\n  };\n\n  Drawable.prototype.drawRange = function(start, size) {\n    if (start == null) {\n      start = this.first;\n    }\n    if (size == null) {\n      size = this.size;\n    }\n    return this.gl.drawArrays(this.mode, start, size);\n  };\n\n  Drawable.prototype.disableAttribs = function(shader) {\n    var location, name, _i, _len, _ref;\n    _ref = this.attribs;\n    for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n      name = _ref[_i];\n      location = shader.attribLoc(name);\n      if (location >= 0) {\n        this.gl.disableVertexAttribArray(location);\n      }\n    }\n    return this;\n  };\n\n  Drawable.prototype.uploadList = function(list) {\n    var data;\n    data = new Float32Array(list);\n    return this.upload(data);\n  };\n\n  Drawable.prototype.upload = function(data) {\n    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);\n    this.gl.bufferData(this.gl.ARRAY_BUFFER, data, this.gl.STATIC_DRAW);\n    return this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n  };\n\n  return Drawable;\n\n})();\n});\n    \n    loader.define('/webgl/shader.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Shader, directives, in_use;\n\ndirectives = ['#ifdef GL_FRAGMENT_PRECISION_HIGH', 'precision highp int;', 'precision highp float;', '#else', 'precision mediump int;', 'precision mediump float;', '#endif'];\n\nin_use = null;\n\nreturn Shader = (function() {\n\n  Shader.lastError = '';\n\n  Shader.splitLines = function(path, source) {\n    var i, line, result, _i, _len, _ref;\n    result = [];\n    _ref = source.split('\\n');\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      line = _ref[i];\n      result.push({\n        line: i,\n        text: line,\n        path: path\n      });\n    }\n    return result;\n  };\n\n  Shader.error = 'ShaderError';\n\n  function Shader(gl, path, source) {\n    var dirname;\n    this.gl = gl;\n    this.path = path;\n    dirname = this.path.split('/');\n    dirname.pop();\n    this.dirname = dirname.join('/');\n    this.program = this.gl.createProgram();\n    this.vs = this.gl.createShader(gl.VERTEX_SHADER);\n    this.fs = this.gl.createShader(gl.FRAGMENT_SHADER);\n    this.gl.attachShader(this.program, this.vs);\n    this.gl.attachShader(this.program, this.fs);\n    this.link(source);\n  }\n\n  Shader.prototype.preprocess = function(source) {\n    var global, i, line, lines, match, shaders, type, _i, _len;\n    lines = source.split('\\n');\n    shaders = {\n      'global': [],\n      'fragment': [],\n      'vertex': []\n    };\n    type = 'global';\n    for (i = _i = 0, _len = lines.length; _i < _len; i = ++_i) {\n      line = lines[i];\n      match = line.match(/^(\\w+):$/);\n      if (match) {\n        type = match[1];\n      } else {\n        shaders[type].push({\n          line: i,\n          text: line,\n          path: this.path\n        });\n      }\n    }\n    global = this.resolveLines(shaders.global);\n    shaders.fragment = global.concat(this.resolveLines(shaders.fragment));\n    shaders.vertex = global.concat(this.resolveLines(shaders.vertex));\n    return shaders;\n  };\n\n  Shader.prototype.resolveLines = function(stage) {\n    var abspath, lib, line, match, path, result, _i, _j, _len, _len1;\n    result = [];\n    for (_i = 0, _len = stage.length; _i < _len; _i++) {\n      line = stage[_i];\n      match = line.text.match(/^\\s+#require (\\S+)\\s*$/);\n      if (match) {\n        path = \"\" + match[1] + \".shaderlib\";\n        abspath = loader.resolvePath(this.dirname, path);\n        lib = get(abspath);\n        for (_j = 0, _len1 = lib.length; _j < _len1; _j++) {\n          line = lib[_j];\n          result.push(line);\n        }\n      } else {\n        result.push(line);\n      }\n    }\n    return result;\n  };\n\n  Shader.prototype.concat = function(stage) {\n    var line, result, _i, _j, _len, _len1;\n    result = '';\n    for (_i = 0, _len = directives.length; _i < _len; _i++) {\n      line = directives[_i];\n      result += line + '\\n';\n    }\n    result += '#line 0\\n';\n    for (_j = 0, _len1 = stage.length; _j < _len1; _j++) {\n      line = stage[_j];\n      result += line.text + '\\n';\n    }\n    return result;\n  };\n\n  Shader.prototype.link = function(source) {\n    var error, shaders;\n    shaders = this.preprocess(source);\n    this.compile(this.vs, shaders.vertex);\n    this.compile(this.fs, shaders.fragment);\n    this.gl.linkProgram(this.program);\n    if (!this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS)) {\n      error = \"Shader Link Error for file: \" + this.path + \":\\n\" + (this.gl.getProgramInfoLog(this.program));\n      console.error(error);\n      Shader.lastError = error;\n      throw Shader.error;\n    }\n    this.attrib_cache = {};\n    this.uniform_cache = {};\n    return this.value_cache = {};\n  };\n\n  Shader.prototype.compile = function(shader, lines) {\n    var error, group, source, text, translated;\n    source = this.concat(lines);\n    this.gl.shaderSource(shader, source);\n    this.gl.compileShader(shader);\n    if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n      error = this.gl.getShaderInfoLog(shader);\n      group = \"Shader Compile Error for file: \" + this.path;\n      translated = this.translateError(error, lines);\n      text = group + '\\n' + translated;\n      Shader.lastError = text;\n      console.group(group);\n      console.warn(translated);\n      console.groupEnd();\n      throw Shader.error;\n    }\n  };\n\n  Shader.prototype.translateError = function(error, sourcelines) {\n    var i, line, lineno, match, message, result, sourceline, _i, _len, _ref;\n    result = [];\n    _ref = error.split('\\n');\n    for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {\n      line = _ref[i];\n      match = line.match(/ERROR: \\d+:(\\d+): (.*)/);\n      if (match) {\n        lineno = parseFloat(match[1]);\n        message = match[2];\n        sourceline = sourcelines[lineno - 1];\n        result.push(\"ERROR: Line \" + (sourceline.line + 1) + \": File \" + sourceline.path + \": \" + message + \" SOURCE: \" + sourceline.text);\n      } else {\n        result.push(line);\n      }\n    }\n    return result.join('\\n');\n  };\n\n  Shader.prototype.attribLoc = function(name) {\n    var location;\n    location = this.attrib_cache[name];\n    if (location === void 0) {\n      location = this.attrib_cache[name] = this.gl.getAttribLocation(this.program, name);\n    }\n    if (location >= 0) {\n      this.gl.enableVertexAttribArray(location);\n    }\n    return location;\n  };\n\n  Shader.prototype.use = function() {\n    if (this !== in_use) {\n      in_use = this;\n      this.gl.useProgram(this.program);\n    }\n    return this;\n  };\n\n  Shader.prototype.unbind = function() {\n    if (in_use) {\n      in_use = null;\n      this.gl.useProgram(null);\n    }\n    return this;\n  };\n\n  Shader.prototype.loc = function(name) {\n    var location;\n    location = this.uniform_cache[name];\n    if (location === void 0) {\n      location = this.uniform_cache[name] = this.gl.getUniformLocation(this.program, name);\n    }\n    return location;\n  };\n\n  Shader.prototype.i = function(name, value) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached !== value) {\n      this.value_cache[name] = value;\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform1i(loc, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.f = function(name, value) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached !== value) {\n      this.value_cache[name] = value;\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform1f(loc, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.fv = function(name, values) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform1fv(loc, values);\n    }\n    return this;\n  };\n\n  Shader.prototype.val2 = function(name, a, b) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached) {\n      if (cached.a !== a || cached.b !== b) {\n        cached.a = a;\n        cached.b = b;\n        loc = this.loc(name);\n        if (loc) {\n          this.gl.uniform2f(loc, a, b);\n        }\n      }\n    } else {\n      this.value_cache[name] = {\n        a: a,\n        b: b\n      };\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform2f(loc, a, b);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.val3 = function(name, a, b, c) {\n    var cached, loc;\n    cached = this.value_cache[name];\n    if (cached) {\n      if (cached.a !== a || cached.b !== b || cached.c !== c) {\n        cached.a = a;\n        cached.b = b;\n        cached.c = c;\n        loc = this.loc(name);\n        if (loc) {\n          this.gl.uniform3f(loc, a, b, c);\n        }\n      }\n    } else {\n      this.value_cache[name] = {\n        a: a,\n        b: b,\n        c: c\n      };\n      loc = this.loc(name);\n      if (loc) {\n        this.gl.uniform3f(loc, a, b, c);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.vec2 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform2fv(loc, value);\n    }\n    return this;\n  };\n\n  Shader.prototype.vec3 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform3fv(loc, value);\n    }\n    return this;\n  };\n\n  Shader.prototype.val4 = function(name, a, b, c, d) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform4f(loc, a, b, c, d);\n    }\n    return this;\n  };\n\n  Shader.prototype.vec4 = function(name, a, b, c, e) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniform2f(loc, a, b, c, e);\n    }\n    return this;\n  };\n\n  Shader.prototype.mat4 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      if (value instanceof Mat4) {\n        this.gl.uniformMatrix4fv(loc, this.gl.FALSE, value.data);\n      } else {\n        this.gl.uniformMatrix4fv(loc, this.gl.FALSE, value);\n      }\n    }\n    return this;\n  };\n\n  Shader.prototype.mat3 = function(name, value) {\n    var loc;\n    loc = this.loc(name);\n    if (loc) {\n      this.gl.uniformMatrix3fv(loc, this.gl.FALSE, value.data);\n    }\n    return this;\n  };\n\n  Shader.prototype.draw = function(drawable) {\n    drawable.setPointersForShader(this).draw().disableAttribs(this);\n    return this;\n  };\n\n  return Shader;\n\n})();\n});\n    \n    loader.define('/webgl/sphere.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Sphere, faces, icosahedron, midp, normalize, phi, subdivide, v1, v10, v11, v12, v2, v3, v4, v5, v6, v7, v8, v9, vertexlist,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nphi = (1 + Math.sqrt(5)) / 2;\n\nmidp = function(v1, v2) {\n  var x1, x2, x3, y1, y2, y3, z1, z2, z3;\n  x1 = v1[0];\n  y1 = v1[1];\n  z1 = v1[2];\n  x2 = v2[0];\n  y2 = v2[1];\n  z2 = v2[2];\n  x3 = (x1 + x2) / 2;\n  y3 = (y1 + y2) / 2;\n  z3 = (z1 + z2) / 2;\n  return [x3, y3, z3];\n};\n\nnormalize = function(faces, r) {\n  var face, l, new_face, result, vertex, x, y, z, _i, _j, _len, _len1;\n  if (r == null) {\n    r = 1;\n  }\n  result = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    new_face = [];\n    result.push(new_face);\n    for (_j = 0, _len1 = face.length; _j < _len1; _j++) {\n      vertex = face[_j];\n      x = vertex[0];\n      y = vertex[1];\n      z = vertex[2];\n      l = Math.sqrt(x * x + y * y + z * z);\n      new_face.push([(r * x) / l, (r * y) / l, (r * z) / l]);\n    }\n  }\n  return result;\n};\n\nsubdivide = function(faces) {\n  var face, result, v0, v1, v2, va, vb, vc, _i, _len;\n  result = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    v0 = face[0];\n    v1 = face[1];\n    v2 = face[2];\n    va = midp(v0, v1);\n    vb = midp(v1, v2);\n    vc = midp(v2, v0);\n    result.push([v0, va, vc], [va, v1, vb], [vc, vb, v2], [va, vb, vc]);\n  }\n  return result;\n};\n\nv1 = [1, phi, 0];\n\nv2 = [-1, phi, 0];\n\nv3 = [0, 1, phi];\n\nv4 = [0, 1, -phi];\n\nv5 = [phi, 0, 1];\n\nv6 = [-phi, 0, 1];\n\nv7 = [-phi, 0, -1];\n\nv8 = [phi, 0, -1];\n\nv9 = [0, -1, phi];\n\nv10 = [0, -1, -phi];\n\nv11 = [-1, -phi, 0];\n\nv12 = [1, -phi, 0];\n\nfaces = [[v1, v2, v3], [v2, v1, v4], [v1, v3, v5], [v2, v6, v3], [v2, v7, v6], [v2, v4, v7], [v1, v5, v8], [v1, v8, v4], [v9, v3, v6], [v3, v9, v5], [v4, v10, v7], [v4, v8, v10], [v6, v7, v11], [v6, v11, v9], [v7, v10, v11], [v5, v12, v8], [v12, v5, v9], [v12, v10, v8], [v11, v12, v9], [v12, v11, v10]];\n\nicosahedron = normalize(faces);\n\nvertexlist = function(faces) {\n  var face, vertex, vertices, x, y, z, _i, _j, _len, _len1;\n  vertices = [];\n  for (_i = 0, _len = faces.length; _i < _len; _i++) {\n    face = faces[_i];\n    for (_j = 0, _len1 = face.length; _j < _len1; _j++) {\n      vertex = face[_j];\n      x = vertex[0];\n      y = vertex[1];\n      z = vertex[2];\n      vertices.push(x, y, z);\n    }\n  }\n  return vertices;\n};\n\nreturn Sphere = (function(_super) {\n\n  __extends(Sphere, _super);\n\n  Sphere.prototype.attribs = ['position'];\n\n  Sphere.prototype.pointers = [\n    {\n      name: 'position',\n      size: 3,\n      offset: 0,\n      stride: 3\n    }\n  ];\n\n  Sphere.makeVertices = function(radius, subdivisions) {\n    var i, template, vertices, _i;\n    if (radius == null) {\n      radius = 1;\n    }\n    if (subdivisions == null) {\n      subdivisions = 3;\n    }\n    template = icosahedron;\n    for (i = _i = 0; 0 <= subdivisions ? _i < subdivisions : _i > subdivisions; i = 0 <= subdivisions ? ++_i : --_i) {\n      template = subdivide(template);\n      template = normalize(template);\n    }\n    faces = normalize(template, radius);\n    vertices = vertexlist(faces);\n    return vertices;\n  };\n\n  function Sphere(gl, radius, subdivisions) {\n    var vertices;\n    this.gl = gl;\n    if (radius == null) {\n      radius = 1;\n    }\n    if (subdivisions == null) {\n      subdivisions = 3;\n    }\n    Sphere.__super__.constructor.call(this);\n    vertices = Sphere.makeVertices(radius, subdivisions);\n    this.size = vertices.length / 3;\n    this.uploadList(vertices);\n  }\n\n  return Sphere;\n\n})(require('drawable'));\n});\n    \n    loader.define('/webgl/texture.js', function(exports, require, get){\n    // Generated by CoffeeScript 1.3.3\nvar Cubemap, Framebuffer, Texture, Texture2D,\n  __hasProp = {}.hasOwnProperty,\n  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };\n\nFramebuffer = require('framebuffer').Framebuffer;\n\nTexture = (function() {\n  var bound, ids;\n\n  bound = [];\n\n  ids = 0;\n\n  function Texture() {\n    this.handle = this.gl.createTexture();\n    this.id = ids++;\n    this.unit = null;\n  }\n\n  Texture.prototype.bind = function(unit) {\n    if (unit == null) {\n      unit = 0;\n    }\n    this.unit = unit;\n    if (bound[unit] !== this.id) {\n      this.gl.activeTexture(this.gl.TEXTURE0 + unit);\n      this.gl.bindTexture(this.target, this.handle);\n      bound[unit] = this.id;\n    }\n    return this;\n  };\n\n  Texture.prototype.unbind = function(unit) {\n    if (unit == null) {\n      unit = this.unit;\n    }\n    if (unit && bound[unit] === this.id) {\n      this.gl.activeTexture(this.gl.TEXTURE0 + unit);\n      this.gl.bindTexture(this.target, null);\n      bound[unit] = null;\n    }\n    return this;\n  };\n\n  Texture.prototype.mipmap = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n    this.gl.generateMipmap(this.target);\n    return this;\n  };\n\n  Texture.prototype.mipmapNearest = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR_MIPMAP_LINEAR);\n    this.gl.generateMipmap(this.target);\n    return this;\n  };\n\n  Texture.prototype.linear = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);\n    return this;\n  };\n\n  Texture.prototype.nearest = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST);\n    return this;\n  };\n\n  Texture.prototype.clampToEdge = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);\n    return this;\n  };\n\n  Texture.prototype.repeat = function() {\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT);\n    this.gl.texParameteri(this.target, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT);\n    return this;\n  };\n\n  Texture.prototype.anisotropy = function() {\n    var ext, max;\n    ext = this.gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');\n    if (ext) {\n      max = this.gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY_EXT);\n      this.gl.texParameterf(this.target, ext.TEXTURE_MAX_ANISOTROPY_EXT, max);\n    }\n    return this;\n  };\n\n  return Texture;\n\n})();\n\nexports.Texture2D = Texture2D = (function(_super) {\n\n  __extends(Texture2D, _super);\n\n  function Texture2D(gl, _arg) {\n    var _ref, _ref1, _ref2, _ref3;\n    this.gl = gl;\n    _ref = _arg != null ? _arg : {}, this.channels = _ref.channels, this.format = _ref.format, this.type = _ref.type;\n    Texture2D.__super__.constructor.call(this);\n    if ((_ref1 = this.channels) == null) {\n      this.channels = this.gl.RGBA;\n    }\n    if ((_ref2 = this.format) == null) {\n      this.format = this.gl.RGBA;\n    }\n    if ((_ref3 = this.type) == null) {\n      this.type = this.gl.UNSIGNED_BYTE;\n    }\n    this.target = this.gl.TEXTURE_2D;\n  }\n\n  Texture2D.prototype.upload = function(image) {\n    this.uploadImage(image);\n    return this;\n  };\n\n  Texture2D.prototype.uploadImage = function(image) {\n    this.width = image.width;\n    this.height = image.height;\n    this.gl.texImage2D(this.target, 0, this.channels, this.format, this.type, image);\n    return this;\n  };\n\n  Texture2D.prototype.uploadData = function(data, width, height) {\n    this.width = width;\n    this.height = height;\n    this.gl.texImage2D(this.target, 0, this.channels, width, height, 0, this.format, this.type, data);\n    return this;\n  };\n\n  Texture2D.prototype.setSize = function(width, height) {\n    this.width = width;\n    this.height = height;\n    this.gl.texImage2D(this.target, 0, this.channels, width, height, 0, this.format, this.type, null);\n    return this;\n  };\n\n  Texture2D.prototype.read = function(dst) {\n    if (dst == null) {\n      dst = new Uint8Array(this.width * this.height * 4);\n    }\n    if (this.fbo) {\n      this.fbo.bind();\n    } else {\n      this.fbo = new Framebuffer(this.gl).bind().color(this);\n    }\n    this.gl.readPixels(0, 0, this.width, this.height, this.gl.RGBA, this.gl.UNSIGNED_BYTE, dst);\n    this.fbo.unbind();\n    return dst;\n  };\n\n  Texture2D.prototype.toPNG = function() {\n    var canvas, ctx, data, i, imgdata, result, url, _i, _ref;\n    canvas = document.createElement('canvas');\n    canvas.height = this.height;\n    canvas.width = this.width;\n    ctx = canvas.getContext('2d');\n    imgdata = ctx.createImageData(this.width, this.height);\n    imgdata.data.set(this.read(), 0);\n    ctx.putImageData(imgdata, 0, 0);\n    url = canvas.toDataURL('image/png');\n    data = atob(url.split(',')[1]);\n    result = new Uint8Array(data.length);\n    for (i = _i = 0, _ref = data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {\n      result[i] = data.charCodeAt(i);\n    }\n    return result;\n  };\n\n  return Texture2D;\n\n})(Texture);\n\nexports.Cubemap = Cubemap = (function(_super) {\n\n  __extends(Cubemap, _super);\n\n  function Cubemap(gl) {\n    this.gl = gl;\n    Cubemap.__super__.constructor.call(this);\n    this.target = this.gl.TEXTURE_CUBE_MAP;\n    this.up = this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y;\n    this.down = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y;\n    this.right = this.gl.TEXTURE_CUBE_MAP_POSITIVE_X;\n    this.left = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X;\n    this.back = this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z;\n    this.front = this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z;\n  }\n\n  Cubemap.prototype.uploadSide = function(name, image) {\n    return this.gl.texImage2D(this.gl['TEXTURE_CUBE_MAP_' + name], 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, image);\n  };\n\n  Cubemap.prototype.upload = function(folder, ext) {\n    if (ext == null) {\n      ext = 'jpg';\n    }\n    this.uploadSide('POSITIVE_Y', folder.get(\"up.\" + ext));\n    this.uploadSide('NEGATIVE_Y', folder.get(\"down.\" + ext));\n    this.uploadSide('POSITIVE_X', folder.get(\"right.\" + ext));\n    this.uploadSide('NEGATIVE_X', folder.get(\"left.\" + ext));\n    this.uploadSide('POSITIVE_Z', folder.get(\"front.\" + ext));\n    this.uploadSide('NEGATIVE_Z', folder.get(\"back.\" + ext));\n    return this;\n  };\n\n  Cubemap.prototype.setSize = function(size) {\n    this.size = size;\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    this.gl.texImage2D(this.gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, this.gl.RGBA, this.size, this.size, 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);\n    return this;\n  };\n\n  return Cubemap;\n\n})(Texture);\n});\n    \n$(function(){loader.main()});"
  },
  {
    "path": "www/index.html",
    "content": "<!doctype HTML>\n<html>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n    <title>Deferred Irradiance Volumes</title>\n    <script src=\"code.js\"></script>\n    <style type=\"text/css\">\n        body{\n            /* background-color: black; */\n            background: #b5bdc8;\n            background: #45484d;\n            background: -moz-linear-gradient(top, #45484d 0%, #000000 100%);\n            background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#45484d), color-stop(100%,#000000));\n            background: -webkit-linear-gradient(top, #45484d 0%,#000000 100%);\n            background: -o-linear-gradient(top, #45484d 0%,#000000 100%);\n            background: -ms-linear-gradient(top, #45484d 0%,#000000 100%);\n            background: linear-gradient(to bottom, #45484d 0%,#000000 100%);\n            filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#45484d', endColorstr='#000000',GradientType=0 );\n        }\n\n\n        html, body, canvas, #ui{\n            color: white;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            font-family: sans-serif;\n        }\n\n        html, body, div, canvas, div{\n            margin: 0;\n            padding: 0;\n        }\n\n        #ui, canvas{\n            position: absolute;\n            top: 0px;\n            left: 0px;\n            text-shadow: black 1px 1px 3px;\n        }\n        canvas{\n            display: none;\n        }\n        a{\n            color: #f62;\n            text-decoration: none;\n        }\n        #windowlabel{\n            position: absolute;\n            top: 20px;\n            left: 0px;\n            width: 100%;\n            font-size: 26px;\n            text-align: center;\n        }\n        #backlink{\n            position: absolute;\n            color: #88ff00;\n            font-size: 14px;\n            top: 5px;\n            left: 5px;\n            cursor: pointer;\n            text-shadow: black 0px 3px 7px;\n        }\n        #backlink:hover{\n            color: white;\n        }\n    </style>\n    <body>\n        <canvas id=\"display\"></canvas>\n        <div id=\"ui\"></div>\n        <a id=\"backlink\" href=\"http://codeflow.org/entries/2012/aug/25/webgl-deferred-irradiance-volumes/\">Blog Entry</a>\n    </body>\n</html>\n"
  }
]