[
  {
    "path": ".gitignore",
    "content": "\nnode_modules\n# IDEs and editors\n.idea\n.project\n.classpath\n.c9/\n*.launch\n.settings/\n*.sublime-workspace\n\n# IDE - VSCode\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# next.js build output\n.next\n\n# Lerna\nlerna-debug.log\n\n# System Files\n.DS_Store\nThumbs.db\n\n# node modules\nnode_modules\n\n# documentation\nbuild/docs/\n\npackage-lock.json\n.DS_Store\nsource/build/\nstatic/"
  },
  {
    "path": ".npmignore",
    "content": "DS_Store\ngit/\nnode_modules/\nexample/\nlib/\n.*.swp\n.DS_Store\n.git\n.hg\n.npmrc\n.lock-wscript\n.svn\n.wafpickle-*\nconfig.gypi\nCVS\nnpm-debug.log"
  },
  {
    "path": "README.md",
    "content": "three.proton\n======\n\nthree.proton is a magical 3d particle engine using [three.js](https://github.com/mrdoob/three.js). It is based on the [Proton](https://github.com/drawcall/Proton) Engine library. It inherited Proton's most api.<br>\nI think it is the simplest three.js particle engine.Check out examples at [https://drawcall.github.io/three.proton/](https://drawcall.github.io/three.proton/)<br>\n\n```shell\nnpm install three three.proton.js\n```\n\n## Features\n- Four kinds of renderers\n  - MeshRender \n  - SpriteRender \n  - PointsRender \n  - CustomRender \n\n- Three kinds of emitters which can simulate many different physical effects\n  - Emitter \n  - BehaviourEmitter \n  - FollowEmitter \n  \n- Perfectly compatible with the three.js library. \n\n## Demo\n\n<p align=\"center\">\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/eightdiagrams.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/1-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/customrender.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/2-min.gif\" /></a>\n  <a href=\"https://codesandbox.io/s/three-mesh-modifiers-website-b55p6?file=/src/components/FollowEffect.js\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/4-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/meshrender-collision.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/3-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/meshzone.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/5-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/spriterender-pointzone.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/6-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/helloworld.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/7-min.gif\" /></a>\n  <a href=\"https://drawcall.github.io/three.proton/engine/example/spriterender-snow.html\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/8-min.gif\" /></a>\n  <a href=\"https://codesandbox.io/s/three-spriterender-39rqy\"><img width=\"274\" src=\"https://drawcall.github.io/three.proton/images/thumb/9-min.gif\" /></a>\n</p>\n<p align=\"middle\">\n  <i>These demos are real, you can click them! They contain the full code, too.</i>\n</p>\n\n## Installation\n\n#### Import library\n\n```javascript\nimport * as THREE from 'three';\nimport Proton from 'three.proton.js';\n```\n\n#### Include in html\n```javascript\n<script type=\"text/javascript\" src=\"./js/three.min.js\"></script> \n<script type=\"text/javascript\" src=\"./js/three.proton.min.js\"></script> \n```\n\n## Usage\n```javascript\nvar proton = new Proton();\nvar emitter = new Proton.Emitter();\n\n//setRate\nemitter.rate = new Proton.Rate(new Proton.Span(4, 16), new Proton.Span(.01));\n\n//addInitialize\nemitter.addInitialize(new Proton.Position(new Proton.PointZone(0, 0)));\nemitter.addInitialize(new Proton.Mass(1));\nemitter.addInitialize(new Proton.Radius(6, 12));\nemitter.addInitialize(new Proton.Life(3));\nemitter.addInitialize(new Proton.V(45, new Proton.Vector3D(0, 1, 0), 180));\n\n//addBehaviour\nemitter.addBehaviour(new Proton.Alpha(1, 0));\nemitter.addBehaviour(new Proton.Scale(.1, 1.3));\n\nvar color1 = new THREE.Color();\nvar color2 = new THREE.Color();\nvar colorBehaviour = new Proton.Color(color1, color2);\nemitter.addBehaviour(colorBehaviour);\nemitter.emit();\n\n//add emitter\nproton.addEmitter(emitter);\n\n//add renderer\nproton.addRender(new Proton.SpriteRender(scene));\n```\n\n## Building three.proton\nNode is a dependency, use terminal to install it with with:<br>\n`git clone git://github.com/drawcall/three.proton.git`<br>\nThen navigate to the build directory by running:<br>\n`cd ./build`<br>\nFinally run the build command:<br>\n`node build.js`\n\n## License\nProton is released under the MIT License. http://www.opensource.org/licenses/mit-license\n"
  },
  {
    "path": "build/build.js",
    "content": "var fs = require(\"fs\"),\n    uglify = {\n        parser: require(\"./lib/parse-js.js\"),\n        processor: require(\"./lib/process.js\")\n    },\n\n    // Set the config filename\n    configfile = \"config\",\n\n    config, version, source_dir, output_full, output_min, head, umd, filenames, foot, i,\n    ast, minified_source,\n\n    files = [],\n    numFiles = 0,\n\n    source = \"\";\n\n// Get config file\nconsole.log(\"Reading config file...\");\nconfig = fs.readFileSync(configfile, \"UTF-8\");\n\n// Get variables from config file\nversion = /^version = (.*)$/m.exec(config)[1],\n    source_dir = /^source_dir = (.*)$/m.exec(config)[1],\n    output_full = /^output_full = (.*)$/m.exec(config)[1].replace(\"{version}\", version),\n    output_min = /^output_min = (.*)$/m.exec(config)[1].replace(\"{version}\", version),\n    head = /head\\s-----\\s([\\s\\S]*?)-----\\s/g.exec(config)[1].replace(\"{version}\", version).replace(\"{year}\", \"2011-\" + (new Date()).getFullYear()),\n    umd = /umd\\s-----\\s([\\s\\S]*?)-----\\s/g.exec(config)[1],\n    filenames = /files\\s-----\\s([\\s\\S]*?)\\s-----/g.exec(config)[1].split(/\\s/);\n\nnumFiles = filenames.length;\n\n// Get all the source files\nfor (i = 0; i < filenames.length; i++) {\n    console.log(\"Reading file: \" + filenames[i]);\n\n    // Add current file\n    files.push({\n        name: filenames[i],\n        content: fs.readFileSync(source_dir + filenames[i], \"UTF-8\")\n    });\n}\n\n// Start the building process\nconsole.log(\"Building source file...\");\n\nsource = head + umd;\nfor (i = 0; i < numFiles; i++) {\n\n    if (files[i].name === \"core/Proton.js\") {\n        files[i].content = files[i].content.replace(/\\}(\\s|)\\)(\\s|)\\(window(\\s|)\\);/, \"\");\n        files[i].content = files[i].content.replace(/\\(function\\(window\\,\\sundefined\\)\\s\\{/, \"\");\n        files[i].content = files[i].content.replace(/window\\.Proton\\s\\=\\sProton\\;/, \"\");\n    } else {\n        files[i].content = files[i].content.replace(/\\(function(\\s|)\\((\\s|)Proton,(\\s|)undefined(\\s|)\\)(\\s|)\\{/, \"\");\n        files[i].content = files[i].content.replace(/\\}(\\s|)\\)(\\s|)\\((\\s|)Proton(\\s|)\\);/, \"\");\n    }\n\n    // Append the file to the full source\n    source += \"\\n\" + files[i].content;\n\n    // Append the end of the core wrapper\n    if (i === numFiles - 1) {\n        //source += \"\\n})(window);\";\n        source += \"    return Proton;\\n}));\";\n    }\n}\n\nfunction noop(){}\n\n///console.log(umd);\n// Save source to output file\nfs.writeFile(output_full, source, \"UTF-8\", noop);\nconsole.log(\"Source file saved as: \" + output_full);\n\n// Run UglifyJS to minify the source\nconsole.log(\"Minifying source with UglifyJS...\");\n\nast = uglify.parser.parse(source);\nast = uglify.processor.ast_mangle(ast);\nast = uglify.processor.ast_squeeze(ast);\nast = uglify.processor.ast_squeeze_more(ast);\nminified_source = uglify.processor.gen_code(ast);\n\n// Save minified source file\nfs.writeFile(output_min, head + minified_source, \"UTF-8\", noop);\nconsole.log(\"Minified source file saved as: \" + output_min);\n"
  },
  {
    "path": "build/config",
    "content": "version = 0.2.0\nsource_dir = ../src/\noutput_full = three.proton.js\noutput_min = three.proton.min.js\n\nhead\n-----\n/*!\n * three.proton v{version}\n * https://github.com/drawcall/three.proton\n *\n * Copyright {year}, ajiemath\n * Licensed under the MIT license\n * http://www.opensource.org/licenses/mit-license\n *\n */\n-----\n\numd\n-----\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('three')) :\n  typeof define === 'function' && define.amd ? define(['three'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Proton = factory(global.THREE));\n}(this, function (THREE) { \n-----\n\nfiles\n-----\ncore/Proton.js\nevents/EventDispatcher.js\nutils/Util.js\nutils/ColorUtil.js\nutils/THREEUtil.js\nutils/PUID.js\ncore/Particle.js\ncore/Pool.js\nmath/MathUtils.js\nmath/Integration.js\nmath/Vector3D.js\nmath/Polar3D.js\nmath/Span.js\nmath/ArraySpan.js\nmath/Quaternion.js\nmath/Box.js\nbehaviour/Behaviour.js\ninitialize/Rate.js\ninitialize/Initialize.js\ninitialize/InitializeUtil.js\ninitialize/Life.js\ninitialize/Position.js\ninitialize/Velocity.js\ninitialize/Mass.js\ninitialize/Radius.js\ninitialize/Body.js\nbehaviour/Force.js\nbehaviour/Attraction.js\nbehaviour/RandomDrift.js\nbehaviour/Repulsion.js\nbehaviour/Gravity.js\nbehaviour/Collision.js\nbehaviour/CrossZone.js\nbehaviour/Alpha.js\nbehaviour/Scale.js\nbehaviour/Rotate.js\nbehaviour/Color.js\nbehaviour/Spring.js\nemitter/Emitter.js\nemitter/BehaviourEmitter.js\nemitter/FollowEmitter.js\nease/ease.js\nrender/BaseRender.js\nrender/MeshRender.js\nrender/PointsRender.js\nrender/SpriteRender.js\nrender/CustomRender.js\nzone/Zone.js\nzone/LineZone.js\nzone/SphereZone.js\nzone/MeshZone.js\nzone/PointZone.js\nzone/BoxZone.js\nzone/ScreenZone.js\ndebug/log.js\ndebug/Debug.js\n-----\n"
  },
  {
    "path": "build/lib/parse-js.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n\n  This version is suitable for Node.js.  With minimal changes (the\n  exports stuff) it should work on any JS platform.\n\n  This file contains the tokenizer/parser.  It is a port to JavaScript\n  of parse-js [1], a JavaScript parser library written in Common Lisp\n  by Marijn Haverbeke.  Thank you Marijn!\n\n  [1] http://marijn.haverbeke.nl/parse-js/\n\n  Exported functions:\n\n    - tokenizer(code) -- returns a function.  Call the returned\n      function to fetch the next token.\n\n    - parse(code) -- returns an AST of the given JavaScript code.\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n    Based on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n/* -----[ Tokenizer (constants) ]----- */\n\nvar KEYWORDS = array_to_hash([\n        \"break\",\n        \"case\",\n        \"catch\",\n        \"const\",\n        \"continue\",\n        \"default\",\n        \"delete\",\n        \"do\",\n        \"else\",\n        \"finally\",\n        \"for\",\n        \"function\",\n        \"if\",\n        \"in\",\n        \"instanceof\",\n        \"new\",\n        \"return\",\n        \"switch\",\n        \"throw\",\n        \"try\",\n        \"typeof\",\n        \"var\",\n        \"void\",\n        \"while\",\n        \"with\"\n]);\n\nvar RESERVED_WORDS = array_to_hash([\n        \"abstract\",\n        \"boolean\",\n        \"byte\",\n        \"char\",\n        \"class\",\n        \"debugger\",\n        \"double\",\n        \"enum\",\n        \"export\",\n        \"extends\",\n        \"final\",\n        \"float\",\n        \"goto\",\n        \"implements\",\n        \"import\",\n        \"int\",\n        \"interface\",\n        \"long\",\n        \"native\",\n        \"package\",\n        \"private\",\n        \"protected\",\n        \"public\",\n        \"short\",\n        \"static\",\n        \"super\",\n        \"synchronized\",\n        \"throws\",\n        \"transient\",\n        \"volatile\"\n]);\n\nvar KEYWORDS_BEFORE_EXPRESSION = array_to_hash([\n        \"return\",\n        \"new\",\n        \"delete\",\n        \"throw\",\n        \"else\",\n        \"case\"\n]);\n\nvar KEYWORDS_ATOM = array_to_hash([\n        \"false\",\n        \"null\",\n        \"true\",\n        \"undefined\"\n]);\n\nvar OPERATOR_CHARS = array_to_hash(characters(\"+-*&%=<>!?|~^\"));\n\nvar RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;\nvar RE_OCT_NUMBER = /^0[0-7]+$/;\nvar RE_DEC_NUMBER = /^\\d*\\.?\\d*(?:e[+-]?\\d*(?:\\d\\.?|\\.?\\d)\\d*)?$/i;\n\nvar OPERATORS = array_to_hash([\n        \"in\",\n        \"instanceof\",\n        \"typeof\",\n        \"new\",\n        \"void\",\n        \"delete\",\n        \"++\",\n        \"--\",\n        \"+\",\n        \"-\",\n        \"!\",\n        \"~\",\n        \"&\",\n        \"|\",\n        \"^\",\n        \"*\",\n        \"/\",\n        \"%\",\n        \">>\",\n        \"<<\",\n        \">>>\",\n        \"<\",\n        \">\",\n        \"<=\",\n        \">=\",\n        \"==\",\n        \"===\",\n        \"!=\",\n        \"!==\",\n        \"?\",\n        \"=\",\n        \"+=\",\n        \"-=\",\n        \"/=\",\n        \"*=\",\n        \"%=\",\n        \">>=\",\n        \"<<=\",\n        \">>>=\",\n        \"%=\",\n        \"|=\",\n        \"^=\",\n        \"&=\",\n        \"&&\",\n        \"||\"\n]);\n\nvar WHITESPACE_CHARS = array_to_hash(characters(\" \\n\\r\\t\\u200b\"));\n\nvar PUNC_BEFORE_EXPRESSION = array_to_hash(characters(\"[{}(,.;:\"));\n\nvar PUNC_CHARS = array_to_hash(characters(\"[]{}(),;:\"));\n\nvar REGEXP_MODIFIERS = array_to_hash(characters(\"gmsiy\"));\n\n/* -----[ Tokenizer ]----- */\n\n// regexps adapted from http://xregexp.com/plugins/#unicode\nvar UNICODE = {\n        letter: new RegExp(\"[\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02C1\\\\u02C6-\\\\u02D1\\\\u02E0-\\\\u02E4\\\\u02EC\\\\u02EE\\\\u0370-\\\\u0374\\\\u0376\\\\u0377\\\\u037A-\\\\u037D\\\\u0386\\\\u0388-\\\\u038A\\\\u038C\\\\u038E-\\\\u03A1\\\\u03A3-\\\\u03F5\\\\u03F7-\\\\u0481\\\\u048A-\\\\u0523\\\\u0531-\\\\u0556\\\\u0559\\\\u0561-\\\\u0587\\\\u05D0-\\\\u05EA\\\\u05F0-\\\\u05F2\\\\u0621-\\\\u064A\\\\u066E\\\\u066F\\\\u0671-\\\\u06D3\\\\u06D5\\\\u06E5\\\\u06E6\\\\u06EE\\\\u06EF\\\\u06FA-\\\\u06FC\\\\u06FF\\\\u0710\\\\u0712-\\\\u072F\\\\u074D-\\\\u07A5\\\\u07B1\\\\u07CA-\\\\u07EA\\\\u07F4\\\\u07F5\\\\u07FA\\\\u0904-\\\\u0939\\\\u093D\\\\u0950\\\\u0958-\\\\u0961\\\\u0971\\\\u0972\\\\u097B-\\\\u097F\\\\u0985-\\\\u098C\\\\u098F\\\\u0990\\\\u0993-\\\\u09A8\\\\u09AA-\\\\u09B0\\\\u09B2\\\\u09B6-\\\\u09B9\\\\u09BD\\\\u09CE\\\\u09DC\\\\u09DD\\\\u09DF-\\\\u09E1\\\\u09F0\\\\u09F1\\\\u0A05-\\\\u0A0A\\\\u0A0F\\\\u0A10\\\\u0A13-\\\\u0A28\\\\u0A2A-\\\\u0A30\\\\u0A32\\\\u0A33\\\\u0A35\\\\u0A36\\\\u0A38\\\\u0A39\\\\u0A59-\\\\u0A5C\\\\u0A5E\\\\u0A72-\\\\u0A74\\\\u0A85-\\\\u0A8D\\\\u0A8F-\\\\u0A91\\\\u0A93-\\\\u0AA8\\\\u0AAA-\\\\u0AB0\\\\u0AB2\\\\u0AB3\\\\u0AB5-\\\\u0AB9\\\\u0ABD\\\\u0AD0\\\\u0AE0\\\\u0AE1\\\\u0B05-\\\\u0B0C\\\\u0B0F\\\\u0B10\\\\u0B13-\\\\u0B28\\\\u0B2A-\\\\u0B30\\\\u0B32\\\\u0B33\\\\u0B35-\\\\u0B39\\\\u0B3D\\\\u0B5C\\\\u0B5D\\\\u0B5F-\\\\u0B61\\\\u0B71\\\\u0B83\\\\u0B85-\\\\u0B8A\\\\u0B8E-\\\\u0B90\\\\u0B92-\\\\u0B95\\\\u0B99\\\\u0B9A\\\\u0B9C\\\\u0B9E\\\\u0B9F\\\\u0BA3\\\\u0BA4\\\\u0BA8-\\\\u0BAA\\\\u0BAE-\\\\u0BB9\\\\u0BD0\\\\u0C05-\\\\u0C0C\\\\u0C0E-\\\\u0C10\\\\u0C12-\\\\u0C28\\\\u0C2A-\\\\u0C33\\\\u0C35-\\\\u0C39\\\\u0C3D\\\\u0C58\\\\u0C59\\\\u0C60\\\\u0C61\\\\u0C85-\\\\u0C8C\\\\u0C8E-\\\\u0C90\\\\u0C92-\\\\u0CA8\\\\u0CAA-\\\\u0CB3\\\\u0CB5-\\\\u0CB9\\\\u0CBD\\\\u0CDE\\\\u0CE0\\\\u0CE1\\\\u0D05-\\\\u0D0C\\\\u0D0E-\\\\u0D10\\\\u0D12-\\\\u0D28\\\\u0D2A-\\\\u0D39\\\\u0D3D\\\\u0D60\\\\u0D61\\\\u0D7A-\\\\u0D7F\\\\u0D85-\\\\u0D96\\\\u0D9A-\\\\u0DB1\\\\u0DB3-\\\\u0DBB\\\\u0DBD\\\\u0DC0-\\\\u0DC6\\\\u0E01-\\\\u0E30\\\\u0E32\\\\u0E33\\\\u0E40-\\\\u0E46\\\\u0E81\\\\u0E82\\\\u0E84\\\\u0E87\\\\u0E88\\\\u0E8A\\\\u0E8D\\\\u0E94-\\\\u0E97\\\\u0E99-\\\\u0E9F\\\\u0EA1-\\\\u0EA3\\\\u0EA5\\\\u0EA7\\\\u0EAA\\\\u0EAB\\\\u0EAD-\\\\u0EB0\\\\u0EB2\\\\u0EB3\\\\u0EBD\\\\u0EC0-\\\\u0EC4\\\\u0EC6\\\\u0EDC\\\\u0EDD\\\\u0F00\\\\u0F40-\\\\u0F47\\\\u0F49-\\\\u0F6C\\\\u0F88-\\\\u0F8B\\\\u1000-\\\\u102A\\\\u103F\\\\u1050-\\\\u1055\\\\u105A-\\\\u105D\\\\u1061\\\\u1065\\\\u1066\\\\u106E-\\\\u1070\\\\u1075-\\\\u1081\\\\u108E\\\\u10A0-\\\\u10C5\\\\u10D0-\\\\u10FA\\\\u10FC\\\\u1100-\\\\u1159\\\\u115F-\\\\u11A2\\\\u11A8-\\\\u11F9\\\\u1200-\\\\u1248\\\\u124A-\\\\u124D\\\\u1250-\\\\u1256\\\\u1258\\\\u125A-\\\\u125D\\\\u1260-\\\\u1288\\\\u128A-\\\\u128D\\\\u1290-\\\\u12B0\\\\u12B2-\\\\u12B5\\\\u12B8-\\\\u12BE\\\\u12C0\\\\u12C2-\\\\u12C5\\\\u12C8-\\\\u12D6\\\\u12D8-\\\\u1310\\\\u1312-\\\\u1315\\\\u1318-\\\\u135A\\\\u1380-\\\\u138F\\\\u13A0-\\\\u13F4\\\\u1401-\\\\u166C\\\\u166F-\\\\u1676\\\\u1681-\\\\u169A\\\\u16A0-\\\\u16EA\\\\u1700-\\\\u170C\\\\u170E-\\\\u1711\\\\u1720-\\\\u1731\\\\u1740-\\\\u1751\\\\u1760-\\\\u176C\\\\u176E-\\\\u1770\\\\u1780-\\\\u17B3\\\\u17D7\\\\u17DC\\\\u1820-\\\\u1877\\\\u1880-\\\\u18A8\\\\u18AA\\\\u1900-\\\\u191C\\\\u1950-\\\\u196D\\\\u1970-\\\\u1974\\\\u1980-\\\\u19A9\\\\u19C1-\\\\u19C7\\\\u1A00-\\\\u1A16\\\\u1B05-\\\\u1B33\\\\u1B45-\\\\u1B4B\\\\u1B83-\\\\u1BA0\\\\u1BAE\\\\u1BAF\\\\u1C00-\\\\u1C23\\\\u1C4D-\\\\u1C4F\\\\u1C5A-\\\\u1C7D\\\\u1D00-\\\\u1DBF\\\\u1E00-\\\\u1F15\\\\u1F18-\\\\u1F1D\\\\u1F20-\\\\u1F45\\\\u1F48-\\\\u1F4D\\\\u1F50-\\\\u1F57\\\\u1F59\\\\u1F5B\\\\u1F5D\\\\u1F5F-\\\\u1F7D\\\\u1F80-\\\\u1FB4\\\\u1FB6-\\\\u1FBC\\\\u1FBE\\\\u1FC2-\\\\u1FC4\\\\u1FC6-\\\\u1FCC\\\\u1FD0-\\\\u1FD3\\\\u1FD6-\\\\u1FDB\\\\u1FE0-\\\\u1FEC\\\\u1FF2-\\\\u1FF4\\\\u1FF6-\\\\u1FFC\\\\u2071\\\\u207F\\\\u2090-\\\\u2094\\\\u2102\\\\u2107\\\\u210A-\\\\u2113\\\\u2115\\\\u2119-\\\\u211D\\\\u2124\\\\u2126\\\\u2128\\\\u212A-\\\\u212D\\\\u212F-\\\\u2139\\\\u213C-\\\\u213F\\\\u2145-\\\\u2149\\\\u214E\\\\u2183\\\\u2184\\\\u2C00-\\\\u2C2E\\\\u2C30-\\\\u2C5E\\\\u2C60-\\\\u2C6F\\\\u2C71-\\\\u2C7D\\\\u2C80-\\\\u2CE4\\\\u2D00-\\\\u2D25\\\\u2D30-\\\\u2D65\\\\u2D6F\\\\u2D80-\\\\u2D96\\\\u2DA0-\\\\u2DA6\\\\u2DA8-\\\\u2DAE\\\\u2DB0-\\\\u2DB6\\\\u2DB8-\\\\u2DBE\\\\u2DC0-\\\\u2DC6\\\\u2DC8-\\\\u2DCE\\\\u2DD0-\\\\u2DD6\\\\u2DD8-\\\\u2DDE\\\\u2E2F\\\\u3005\\\\u3006\\\\u3031-\\\\u3035\\\\u303B\\\\u303C\\\\u3041-\\\\u3096\\\\u309D-\\\\u309F\\\\u30A1-\\\\u30FA\\\\u30FC-\\\\u30FF\\\\u3105-\\\\u312D\\\\u3131-\\\\u318E\\\\u31A0-\\\\u31B7\\\\u31F0-\\\\u31FF\\\\u3400\\\\u4DB5\\\\u4E00\\\\u9FC3\\\\uA000-\\\\uA48C\\\\uA500-\\\\uA60C\\\\uA610-\\\\uA61F\\\\uA62A\\\\uA62B\\\\uA640-\\\\uA65F\\\\uA662-\\\\uA66E\\\\uA67F-\\\\uA697\\\\uA717-\\\\uA71F\\\\uA722-\\\\uA788\\\\uA78B\\\\uA78C\\\\uA7FB-\\\\uA801\\\\uA803-\\\\uA805\\\\uA807-\\\\uA80A\\\\uA80C-\\\\uA822\\\\uA840-\\\\uA873\\\\uA882-\\\\uA8B3\\\\uA90A-\\\\uA925\\\\uA930-\\\\uA946\\\\uAA00-\\\\uAA28\\\\uAA40-\\\\uAA42\\\\uAA44-\\\\uAA4B\\\\uAC00\\\\uD7A3\\\\uF900-\\\\uFA2D\\\\uFA30-\\\\uFA6A\\\\uFA70-\\\\uFAD9\\\\uFB00-\\\\uFB06\\\\uFB13-\\\\uFB17\\\\uFB1D\\\\uFB1F-\\\\uFB28\\\\uFB2A-\\\\uFB36\\\\uFB38-\\\\uFB3C\\\\uFB3E\\\\uFB40\\\\uFB41\\\\uFB43\\\\uFB44\\\\uFB46-\\\\uFBB1\\\\uFBD3-\\\\uFD3D\\\\uFD50-\\\\uFD8F\\\\uFD92-\\\\uFDC7\\\\uFDF0-\\\\uFDFB\\\\uFE70-\\\\uFE74\\\\uFE76-\\\\uFEFC\\\\uFF21-\\\\uFF3A\\\\uFF41-\\\\uFF5A\\\\uFF66-\\\\uFFBE\\\\uFFC2-\\\\uFFC7\\\\uFFCA-\\\\uFFCF\\\\uFFD2-\\\\uFFD7\\\\uFFDA-\\\\uFFDC]\"),\n        non_spacing_mark: new RegExp(\"[\\\\u0300-\\\\u036F\\\\u0483-\\\\u0487\\\\u0591-\\\\u05BD\\\\u05BF\\\\u05C1\\\\u05C2\\\\u05C4\\\\u05C5\\\\u05C7\\\\u0610-\\\\u061A\\\\u064B-\\\\u065E\\\\u0670\\\\u06D6-\\\\u06DC\\\\u06DF-\\\\u06E4\\\\u06E7\\\\u06E8\\\\u06EA-\\\\u06ED\\\\u0711\\\\u0730-\\\\u074A\\\\u07A6-\\\\u07B0\\\\u07EB-\\\\u07F3\\\\u0816-\\\\u0819\\\\u081B-\\\\u0823\\\\u0825-\\\\u0827\\\\u0829-\\\\u082D\\\\u0900-\\\\u0902\\\\u093C\\\\u0941-\\\\u0948\\\\u094D\\\\u0951-\\\\u0955\\\\u0962\\\\u0963\\\\u0981\\\\u09BC\\\\u09C1-\\\\u09C4\\\\u09CD\\\\u09E2\\\\u09E3\\\\u0A01\\\\u0A02\\\\u0A3C\\\\u0A41\\\\u0A42\\\\u0A47\\\\u0A48\\\\u0A4B-\\\\u0A4D\\\\u0A51\\\\u0A70\\\\u0A71\\\\u0A75\\\\u0A81\\\\u0A82\\\\u0ABC\\\\u0AC1-\\\\u0AC5\\\\u0AC7\\\\u0AC8\\\\u0ACD\\\\u0AE2\\\\u0AE3\\\\u0B01\\\\u0B3C\\\\u0B3F\\\\u0B41-\\\\u0B44\\\\u0B4D\\\\u0B56\\\\u0B62\\\\u0B63\\\\u0B82\\\\u0BC0\\\\u0BCD\\\\u0C3E-\\\\u0C40\\\\u0C46-\\\\u0C48\\\\u0C4A-\\\\u0C4D\\\\u0C55\\\\u0C56\\\\u0C62\\\\u0C63\\\\u0CBC\\\\u0CBF\\\\u0CC6\\\\u0CCC\\\\u0CCD\\\\u0CE2\\\\u0CE3\\\\u0D41-\\\\u0D44\\\\u0D4D\\\\u0D62\\\\u0D63\\\\u0DCA\\\\u0DD2-\\\\u0DD4\\\\u0DD6\\\\u0E31\\\\u0E34-\\\\u0E3A\\\\u0E47-\\\\u0E4E\\\\u0EB1\\\\u0EB4-\\\\u0EB9\\\\u0EBB\\\\u0EBC\\\\u0EC8-\\\\u0ECD\\\\u0F18\\\\u0F19\\\\u0F35\\\\u0F37\\\\u0F39\\\\u0F71-\\\\u0F7E\\\\u0F80-\\\\u0F84\\\\u0F86\\\\u0F87\\\\u0F90-\\\\u0F97\\\\u0F99-\\\\u0FBC\\\\u0FC6\\\\u102D-\\\\u1030\\\\u1032-\\\\u1037\\\\u1039\\\\u103A\\\\u103D\\\\u103E\\\\u1058\\\\u1059\\\\u105E-\\\\u1060\\\\u1071-\\\\u1074\\\\u1082\\\\u1085\\\\u1086\\\\u108D\\\\u109D\\\\u135F\\\\u1712-\\\\u1714\\\\u1732-\\\\u1734\\\\u1752\\\\u1753\\\\u1772\\\\u1773\\\\u17B7-\\\\u17BD\\\\u17C6\\\\u17C9-\\\\u17D3\\\\u17DD\\\\u180B-\\\\u180D\\\\u18A9\\\\u1920-\\\\u1922\\\\u1927\\\\u1928\\\\u1932\\\\u1939-\\\\u193B\\\\u1A17\\\\u1A18\\\\u1A56\\\\u1A58-\\\\u1A5E\\\\u1A60\\\\u1A62\\\\u1A65-\\\\u1A6C\\\\u1A73-\\\\u1A7C\\\\u1A7F\\\\u1B00-\\\\u1B03\\\\u1B34\\\\u1B36-\\\\u1B3A\\\\u1B3C\\\\u1B42\\\\u1B6B-\\\\u1B73\\\\u1B80\\\\u1B81\\\\u1BA2-\\\\u1BA5\\\\u1BA8\\\\u1BA9\\\\u1C2C-\\\\u1C33\\\\u1C36\\\\u1C37\\\\u1CD0-\\\\u1CD2\\\\u1CD4-\\\\u1CE0\\\\u1CE2-\\\\u1CE8\\\\u1CED\\\\u1DC0-\\\\u1DE6\\\\u1DFD-\\\\u1DFF\\\\u20D0-\\\\u20DC\\\\u20E1\\\\u20E5-\\\\u20F0\\\\u2CEF-\\\\u2CF1\\\\u2DE0-\\\\u2DFF\\\\u302A-\\\\u302F\\\\u3099\\\\u309A\\\\uA66F\\\\uA67C\\\\uA67D\\\\uA6F0\\\\uA6F1\\\\uA802\\\\uA806\\\\uA80B\\\\uA825\\\\uA826\\\\uA8C4\\\\uA8E0-\\\\uA8F1\\\\uA926-\\\\uA92D\\\\uA947-\\\\uA951\\\\uA980-\\\\uA982\\\\uA9B3\\\\uA9B6-\\\\uA9B9\\\\uA9BC\\\\uAA29-\\\\uAA2E\\\\uAA31\\\\uAA32\\\\uAA35\\\\uAA36\\\\uAA43\\\\uAA4C\\\\uAAB0\\\\uAAB2-\\\\uAAB4\\\\uAAB7\\\\uAAB8\\\\uAABE\\\\uAABF\\\\uAAC1\\\\uABE5\\\\uABE8\\\\uABED\\\\uFB1E\\\\uFE00-\\\\uFE0F\\\\uFE20-\\\\uFE26]\"),\n        space_combining_mark: new RegExp(\"[\\\\u0903\\\\u093E-\\\\u0940\\\\u0949-\\\\u094C\\\\u094E\\\\u0982\\\\u0983\\\\u09BE-\\\\u09C0\\\\u09C7\\\\u09C8\\\\u09CB\\\\u09CC\\\\u09D7\\\\u0A03\\\\u0A3E-\\\\u0A40\\\\u0A83\\\\u0ABE-\\\\u0AC0\\\\u0AC9\\\\u0ACB\\\\u0ACC\\\\u0B02\\\\u0B03\\\\u0B3E\\\\u0B40\\\\u0B47\\\\u0B48\\\\u0B4B\\\\u0B4C\\\\u0B57\\\\u0BBE\\\\u0BBF\\\\u0BC1\\\\u0BC2\\\\u0BC6-\\\\u0BC8\\\\u0BCA-\\\\u0BCC\\\\u0BD7\\\\u0C01-\\\\u0C03\\\\u0C41-\\\\u0C44\\\\u0C82\\\\u0C83\\\\u0CBE\\\\u0CC0-\\\\u0CC4\\\\u0CC7\\\\u0CC8\\\\u0CCA\\\\u0CCB\\\\u0CD5\\\\u0CD6\\\\u0D02\\\\u0D03\\\\u0D3E-\\\\u0D40\\\\u0D46-\\\\u0D48\\\\u0D4A-\\\\u0D4C\\\\u0D57\\\\u0D82\\\\u0D83\\\\u0DCF-\\\\u0DD1\\\\u0DD8-\\\\u0DDF\\\\u0DF2\\\\u0DF3\\\\u0F3E\\\\u0F3F\\\\u0F7F\\\\u102B\\\\u102C\\\\u1031\\\\u1038\\\\u103B\\\\u103C\\\\u1056\\\\u1057\\\\u1062-\\\\u1064\\\\u1067-\\\\u106D\\\\u1083\\\\u1084\\\\u1087-\\\\u108C\\\\u108F\\\\u109A-\\\\u109C\\\\u17B6\\\\u17BE-\\\\u17C5\\\\u17C7\\\\u17C8\\\\u1923-\\\\u1926\\\\u1929-\\\\u192B\\\\u1930\\\\u1931\\\\u1933-\\\\u1938\\\\u19B0-\\\\u19C0\\\\u19C8\\\\u19C9\\\\u1A19-\\\\u1A1B\\\\u1A55\\\\u1A57\\\\u1A61\\\\u1A63\\\\u1A64\\\\u1A6D-\\\\u1A72\\\\u1B04\\\\u1B35\\\\u1B3B\\\\u1B3D-\\\\u1B41\\\\u1B43\\\\u1B44\\\\u1B82\\\\u1BA1\\\\u1BA6\\\\u1BA7\\\\u1BAA\\\\u1C24-\\\\u1C2B\\\\u1C34\\\\u1C35\\\\u1CE1\\\\u1CF2\\\\uA823\\\\uA824\\\\uA827\\\\uA880\\\\uA881\\\\uA8B4-\\\\uA8C3\\\\uA952\\\\uA953\\\\uA983\\\\uA9B4\\\\uA9B5\\\\uA9BA\\\\uA9BB\\\\uA9BD-\\\\uA9C0\\\\uAA2F\\\\uAA30\\\\uAA33\\\\uAA34\\\\uAA4D\\\\uAA7B\\\\uABE3\\\\uABE4\\\\uABE6\\\\uABE7\\\\uABE9\\\\uABEA\\\\uABEC]\"),\n        connector_punctuation: new RegExp(\"[\\\\u005F\\\\u203F\\\\u2040\\\\u2054\\\\uFE33\\\\uFE34\\\\uFE4D-\\\\uFE4F\\\\uFF3F]\")\n};\n\nfunction is_letter(ch) {\n        return UNICODE.letter.test(ch);\n};\n\nfunction is_digit(ch) {\n        ch = ch.charCodeAt(0);\n        return ch >= 48 && ch <= 57; //XXX: find out if \"UnicodeDigit\" means something else than 0..9\n};\n\nfunction is_alphanumeric_char(ch) {\n        return is_digit(ch) || is_letter(ch);\n};\n\nfunction is_unicode_combining_mark(ch) {\n        return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);\n};\n\nfunction is_unicode_connector_punctuation(ch) {\n        return UNICODE.connector_punctuation.test(ch);\n};\n\nfunction is_identifier_start(ch) {\n        return ch == \"$\" || ch == \"_\" || is_letter(ch);\n};\n\nfunction is_identifier_char(ch) {\n        return is_identifier_start(ch)\n                || is_unicode_combining_mark(ch)\n                || is_digit(ch)\n                || is_unicode_connector_punctuation(ch)\n                || ch == \"\\u200c\" // zero-width non-joiner <ZWNJ>\n                || ch == \"\\u200d\" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)\n        ;\n};\n\nfunction parse_js_number(num) {\n        if (RE_HEX_NUMBER.test(num)) {\n                return parseInt(num.substr(2), 16);\n        } else if (RE_OCT_NUMBER.test(num)) {\n                return parseInt(num.substr(1), 8);\n        } else if (RE_DEC_NUMBER.test(num)) {\n                return parseFloat(num);\n        }\n};\n\nfunction JS_Parse_Error(message, line, col, pos) {\n        this.message = message;\n        this.line = line;\n        this.col = col;\n        this.pos = pos;\n        try {\n                ({})();\n        } catch(ex) {\n                this.stack = ex.stack;\n        };\n};\n\nJS_Parse_Error.prototype.toString = function() {\n        return this.message + \" (line: \" + this.line + \", col: \" + this.col + \", pos: \" + this.pos + \")\" + \"\\n\\n\" + this.stack;\n};\n\nfunction js_error(message, line, col, pos) {\n        throw new JS_Parse_Error(message, line, col, pos);\n};\n\nfunction is_token(token, type, val) {\n        return token.type == type && (val == null || token.value == val);\n};\n\nvar EX_EOF = {};\n\nfunction tokenizer($TEXT) {\n\n        var S = {\n                text            : $TEXT.replace(/\\r\\n?|[\\n\\u2028\\u2029]/g, \"\\n\").replace(/^\\uFEFF/, ''),\n                pos             : 0,\n                tokpos          : 0,\n                line            : 0,\n                tokline         : 0,\n                col             : 0,\n                tokcol          : 0,\n                newline_before  : false,\n                regex_allowed   : false,\n                comments_before : []\n        };\n\n        function peek() { return S.text.charAt(S.pos); };\n\n        function next(signal_eof) {\n                var ch = S.text.charAt(S.pos++);\n                if (signal_eof && !ch)\n                        throw EX_EOF;\n                if (ch == \"\\n\") {\n                        S.newline_before = true;\n                        ++S.line;\n                        S.col = 0;\n                } else {\n                        ++S.col;\n                }\n                return ch;\n        };\n\n        function eof() {\n                return !S.peek();\n        };\n\n        function find(what, signal_eof) {\n                var pos = S.text.indexOf(what, S.pos);\n                if (signal_eof && pos == -1) throw EX_EOF;\n                return pos;\n        };\n\n        function start_token() {\n                S.tokline = S.line;\n                S.tokcol = S.col;\n                S.tokpos = S.pos;\n        };\n\n        function token(type, value, is_comment) {\n                S.regex_allowed = ((type == \"operator\" && !HOP(UNARY_POSTFIX, value)) ||\n                                   (type == \"keyword\" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||\n                                   (type == \"punc\" && HOP(PUNC_BEFORE_EXPRESSION, value)));\n                var ret = {\n                        type  : type,\n                        value : value,\n                        line  : S.tokline,\n                        col   : S.tokcol,\n                        pos   : S.tokpos,\n                        nlb   : S.newline_before\n                };\n                if (!is_comment) {\n                        ret.comments_before = S.comments_before;\n                        S.comments_before = [];\n                }\n                S.newline_before = false;\n                return ret;\n        };\n\n        function skip_whitespace() {\n                while (HOP(WHITESPACE_CHARS, peek()))\n                        next();\n        };\n\n        function read_while(pred) {\n                var ret = \"\", ch = peek(), i = 0;\n                while (ch && pred(ch, i++)) {\n                        ret += next();\n                        ch = peek();\n                }\n                return ret;\n        };\n\n        function parse_error(err) {\n                js_error(err, S.tokline, S.tokcol, S.tokpos);\n        };\n\n        function read_num(prefix) {\n                var has_e = false, after_e = false, has_x = false, has_dot = prefix == \".\";\n                var num = read_while(function(ch, i){\n                        if (ch == \"x\" || ch == \"X\") {\n                                if (has_x) return false;\n                                return has_x = true;\n                        }\n                        if (!has_x && (ch == \"E\" || ch == \"e\")) {\n                                if (has_e) return false;\n                                return has_e = after_e = true;\n                        }\n                        if (ch == \"-\") {\n                                if (after_e || (i == 0 && !prefix)) return true;\n                                return false;\n                        }\n                        if (ch == \"+\") return after_e;\n                        after_e = false;\n                        if (ch == \".\") {\n                                if (!has_dot)\n                                        return has_dot = true;\n                                return false;\n                        }\n                        return is_alphanumeric_char(ch);\n                });\n                if (prefix)\n                        num = prefix + num;\n                var valid = parse_js_number(num);\n                if (!isNaN(valid)) {\n                        return token(\"num\", valid);\n                } else {\n                        parse_error(\"Invalid syntax: \" + num);\n                }\n        };\n\n        function read_escaped_char() {\n                var ch = next(true);\n                switch (ch) {\n                    case \"n\" : return \"\\n\";\n                    case \"r\" : return \"\\r\";\n                    case \"t\" : return \"\\t\";\n                    case \"b\" : return \"\\b\";\n                    case \"v\" : return \"\\v\";\n                    case \"f\" : return \"\\f\";\n                    case \"0\" : return \"\\0\";\n                    case \"x\" : return String.fromCharCode(hex_bytes(2));\n                    case \"u\" : return String.fromCharCode(hex_bytes(4));\n                    default  : return ch;\n                }\n        };\n\n        function hex_bytes(n) {\n                var num = 0;\n                for (; n > 0; --n) {\n                        var digit = parseInt(next(true), 16);\n                        if (isNaN(digit))\n                                parse_error(\"Invalid hex-character pattern in string\");\n                        num = (num << 4) | digit;\n                }\n                return num;\n        };\n\n        function read_string() {\n                return with_eof_error(\"Unterminated string constant\", function(){\n                        var quote = next(), ret = \"\";\n                        for (;;) {\n                                var ch = next(true);\n                                if (ch == \"\\\\\") ch = read_escaped_char();\n                                else if (ch == quote) break;\n                                ret += ch;\n                        }\n                        return token(\"string\", ret);\n                });\n        };\n\n        function read_line_comment() {\n                next();\n                var i = find(\"\\n\"), ret;\n                if (i == -1) {\n                        ret = S.text.substr(S.pos);\n                        S.pos = S.text.length;\n                } else {\n                        ret = S.text.substring(S.pos, i);\n                        S.pos = i;\n                }\n                return token(\"comment1\", ret, true);\n        };\n\n        function read_multiline_comment() {\n                next();\n                return with_eof_error(\"Unterminated multiline comment\", function(){\n                        var i = find(\"*/\", true),\n                            text = S.text.substring(S.pos, i),\n                            tok = token(\"comment2\", text, true);\n                        S.pos = i + 2;\n                        S.line += text.split(\"\\n\").length - 1;\n                        S.newline_before = text.indexOf(\"\\n\") >= 0;\n\n                        // https://github.com/mishoo/UglifyJS/issues/#issue/100\n                        if (/^@cc_on/i.test(text)) {\n                                warn(\"WARNING: at line \" + S.line);\n                                warn(\"*** Found \\\"conditional comment\\\": \" + text);\n                                warn(\"*** UglifyJS DISCARDS ALL COMMENTS.  This means your code might no longer work properly in Internet Explorer.\");\n                        }\n\n                        return tok;\n                });\n        };\n\n        function read_name() {\n                var backslash = false, name = \"\", ch;\n                while ((ch = peek()) != null) {\n                        if (!backslash) {\n                                if (ch == \"\\\\\") backslash = true, next();\n                                else if (is_identifier_char(ch)) name += next();\n                                else break;\n                        }\n                        else {\n                                if (ch != \"u\") parse_error(\"Expecting UnicodeEscapeSequence -- uXXXX\");\n                                ch = read_escaped_char();\n                                if (!is_identifier_char(ch)) parse_error(\"Unicode char: \" + ch.charCodeAt(0) + \" is not valid in identifier\");\n                                name += ch;\n                                backslash = false;\n                        }\n                }\n                return name;\n        };\n\n        function read_regexp() {\n                return with_eof_error(\"Unterminated regular expression\", function(){\n                        var prev_backslash = false, regexp = \"\", ch, in_class = false;\n                        while ((ch = next(true))) if (prev_backslash) {\n                                regexp += \"\\\\\" + ch;\n                                prev_backslash = false;\n                        } else if (ch == \"[\") {\n                                in_class = true;\n                                regexp += ch;\n                        } else if (ch == \"]\" && in_class) {\n                                in_class = false;\n                                regexp += ch;\n                        } else if (ch == \"/\" && !in_class) {\n                                break;\n                        } else if (ch == \"\\\\\") {\n                                prev_backslash = true;\n                        } else {\n                                regexp += ch;\n                        }\n                        var mods = read_name();\n                        return token(\"regexp\", [ regexp, mods ]);\n                });\n        };\n\n        function read_operator(prefix) {\n                function grow(op) {\n                        if (!peek()) return op;\n                        var bigger = op + peek();\n                        if (HOP(OPERATORS, bigger)) {\n                                next();\n                                return grow(bigger);\n                        } else {\n                                return op;\n                        }\n                };\n                return token(\"operator\", grow(prefix || next()));\n        };\n\n        function handle_slash() {\n                next();\n                var regex_allowed = S.regex_allowed;\n                switch (peek()) {\n                    case \"/\":\n                        S.comments_before.push(read_line_comment());\n                        S.regex_allowed = regex_allowed;\n                        return next_token();\n                    case \"*\":\n                        S.comments_before.push(read_multiline_comment());\n                        S.regex_allowed = regex_allowed;\n                        return next_token();\n                }\n                return S.regex_allowed ? read_regexp() : read_operator(\"/\");\n        };\n\n        function handle_dot() {\n                next();\n                return is_digit(peek())\n                        ? read_num(\".\")\n                        : token(\"punc\", \".\");\n        };\n\n        function read_word() {\n                var word = read_name();\n                return !HOP(KEYWORDS, word)\n                        ? token(\"name\", word)\n                        : HOP(OPERATORS, word)\n                        ? token(\"operator\", word)\n                        : HOP(KEYWORDS_ATOM, word)\n                        ? token(\"atom\", word)\n                        : token(\"keyword\", word);\n        };\n\n        function with_eof_error(eof_error, cont) {\n                try {\n                        return cont();\n                } catch(ex) {\n                        if (ex === EX_EOF) parse_error(eof_error);\n                        else throw ex;\n                }\n        };\n\n        function next_token(force_regexp) {\n                if (force_regexp)\n                        return read_regexp();\n                skip_whitespace();\n                start_token();\n                var ch = peek();\n                if (!ch) return token(\"eof\");\n                if (is_digit(ch)) return read_num();\n                if (ch == '\"' || ch == \"'\") return read_string();\n                if (HOP(PUNC_CHARS, ch)) return token(\"punc\", next());\n                if (ch == \".\") return handle_dot();\n                if (ch == \"/\") return handle_slash();\n                if (HOP(OPERATOR_CHARS, ch)) return read_operator();\n                if (ch == \"\\\\\" || is_identifier_start(ch)) return read_word();\n                parse_error(\"Unexpected character '\" + ch + \"'\");\n        };\n\n        next_token.context = function(nc) {\n                if (nc) S = nc;\n                return S;\n        };\n\n        return next_token;\n\n};\n\n/* -----[ Parser (constants) ]----- */\n\nvar UNARY_PREFIX = array_to_hash([\n        \"typeof\",\n        \"void\",\n        \"delete\",\n        \"--\",\n        \"++\",\n        \"!\",\n        \"~\",\n        \"-\",\n        \"+\"\n]);\n\nvar UNARY_POSTFIX = array_to_hash([ \"--\", \"++\" ]);\n\nvar ASSIGNMENT = (function(a, ret, i){\n        while (i < a.length) {\n                ret[a[i]] = a[i].substr(0, a[i].length - 1);\n                i++;\n        }\n        return ret;\n})(\n        [\"+=\", \"-=\", \"/=\", \"*=\", \"%=\", \">>=\", \"<<=\", \">>>=\", \"|=\", \"^=\", \"&=\"],\n        { \"=\": true },\n        0\n);\n\nvar PRECEDENCE = (function(a, ret){\n        for (var i = 0, n = 1; i < a.length; ++i, ++n) {\n                var b = a[i];\n                for (var j = 0; j < b.length; ++j) {\n                        ret[b[j]] = n;\n                }\n        }\n        return ret;\n})(\n        [\n                [\"||\"],\n                [\"&&\"],\n                [\"|\"],\n                [\"^\"],\n                [\"&\"],\n                [\"==\", \"===\", \"!=\", \"!==\"],\n                [\"<\", \">\", \"<=\", \">=\", \"in\", \"instanceof\"],\n                [\">>\", \"<<\", \">>>\"],\n                [\"+\", \"-\"],\n                [\"*\", \"/\", \"%\"]\n        ],\n        {}\n);\n\nvar STATEMENTS_WITH_LABELS = array_to_hash([ \"for\", \"do\", \"while\", \"switch\" ]);\n\nvar ATOMIC_START_TOKEN = array_to_hash([ \"atom\", \"num\", \"string\", \"regexp\", \"name\" ]);\n\n/* -----[ Parser ]----- */\n\nfunction NodeWithToken(str, start, end) {\n        this.name = str;\n        this.start = start;\n        this.end = end;\n};\n\nNodeWithToken.prototype.toString = function() { return this.name; };\n\nfunction parse($TEXT, exigent_mode, embed_tokens) {\n\n        var S = {\n                input       : typeof $TEXT == \"string\" ? tokenizer($TEXT, true) : $TEXT,\n                token       : null,\n                prev        : null,\n                peeked      : null,\n                in_function : 0,\n                in_loop     : 0,\n                labels      : []\n        };\n\n        S.token = next();\n\n        function is(type, value) {\n                return is_token(S.token, type, value);\n        };\n\n        function peek() { return S.peeked || (S.peeked = S.input()); };\n\n        function next() {\n                S.prev = S.token;\n                if (S.peeked) {\n                        S.token = S.peeked;\n                        S.peeked = null;\n                } else {\n                        S.token = S.input();\n                }\n                return S.token;\n        };\n\n        function prev() {\n                return S.prev;\n        };\n\n        function croak(msg, line, col, pos) {\n                var ctx = S.input.context();\n                js_error(msg,\n                         line != null ? line : ctx.tokline,\n                         col != null ? col : ctx.tokcol,\n                         pos != null ? pos : ctx.tokpos);\n        };\n\n        function token_error(token, msg) {\n                croak(msg, token.line, token.col);\n        };\n\n        function unexpected(token) {\n                if (token == null)\n                        token = S.token;\n                token_error(token, \"Unexpected token: \" + token.type + \" (\" + token.value + \")\");\n        };\n\n        function expect_token(type, val) {\n                if (is(type, val)) {\n                        return next();\n                }\n                token_error(S.token, \"Unexpected token \" + S.token.type + \", expected \" + type);\n        };\n\n        function expect(punc) { return expect_token(\"punc\", punc); };\n\n        function can_insert_semicolon() {\n                return !exigent_mode && (\n                        S.token.nlb || is(\"eof\") || is(\"punc\", \"}\")\n                );\n        };\n\n        function semicolon() {\n                if (is(\"punc\", \";\")) next();\n                else if (!can_insert_semicolon()) unexpected();\n        };\n\n        function as() {\n                return slice(arguments);\n        };\n\n        function parenthesised() {\n                expect(\"(\");\n                var ex = expression();\n                expect(\")\");\n                return ex;\n        };\n\n        function add_tokens(str, start, end) {\n                return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);\n        };\n\n        var statement = embed_tokens ? function() {\n                var start = S.token;\n                var ast = $statement.apply(this, arguments);\n                ast[0] = add_tokens(ast[0], start, prev());\n                return ast;\n        } : $statement;\n\n        function $statement() {\n                if (is(\"operator\", \"/\")) {\n                        S.peeked = null;\n                        S.token = S.input(true); // force regexp\n                }\n                switch (S.token.type) {\n                    case \"num\":\n                    case \"string\":\n                    case \"regexp\":\n                    case \"operator\":\n                    case \"atom\":\n                        return simple_statement();\n\n                    case \"name\":\n                        return is_token(peek(), \"punc\", \":\")\n                                ? labeled_statement(prog1(S.token.value, next, next))\n                                : simple_statement();\n\n                    case \"punc\":\n                        switch (S.token.value) {\n                            case \"{\":\n                                return as(\"block\", block_());\n                            case \"[\":\n                            case \"(\":\n                                return simple_statement();\n                            case \";\":\n                                next();\n                                return as(\"block\");\n                            default:\n                                unexpected();\n                        }\n\n                    case \"keyword\":\n                        switch (prog1(S.token.value, next)) {\n                            case \"break\":\n                                return break_cont(\"break\");\n\n                            case \"continue\":\n                                return break_cont(\"continue\");\n\n                            case \"debugger\":\n                                semicolon();\n                                return as(\"debugger\");\n\n                            case \"do\":\n                                return (function(body){\n                                        expect_token(\"keyword\", \"while\");\n                                        return as(\"do\", prog1(parenthesised, semicolon), body);\n                                })(in_loop(statement));\n\n                            case \"for\":\n                                return for_();\n\n                            case \"function\":\n                                return function_(true);\n\n                            case \"if\":\n                                return if_();\n\n                            case \"return\":\n                                if (S.in_function == 0)\n                                        croak(\"'return' outside of function\");\n                                return as(\"return\",\n                                          is(\"punc\", \";\")\n                                          ? (next(), null)\n                                          : can_insert_semicolon()\n                                          ? null\n                                          : prog1(expression, semicolon));\n\n                            case \"switch\":\n                                return as(\"switch\", parenthesised(), switch_block_());\n\n                            case \"throw\":\n                                return as(\"throw\", prog1(expression, semicolon));\n\n                            case \"try\":\n                                return try_();\n\n                            case \"var\":\n                                return prog1(var_, semicolon);\n\n                            case \"const\":\n                                return prog1(const_, semicolon);\n\n                            case \"while\":\n                                return as(\"while\", parenthesised(), in_loop(statement));\n\n                            case \"with\":\n                                return as(\"with\", parenthesised(), statement());\n\n                            default:\n                                unexpected();\n                        }\n                }\n        };\n\n        function labeled_statement(label) {\n                S.labels.push(label);\n                var start = S.token, stat = statement();\n                if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))\n                        unexpected(start);\n                S.labels.pop();\n                return as(\"label\", label, stat);\n        };\n\n        function simple_statement() {\n                return as(\"stat\", prog1(expression, semicolon));\n        };\n\n        function break_cont(type) {\n                var name = is(\"name\") ? S.token.value : null;\n                if (name != null) {\n                        next();\n                        if (!member(name, S.labels))\n                                croak(\"Label \" + name + \" without matching loop or statement\");\n                }\n                else if (S.in_loop == 0)\n                        croak(type + \" not inside a loop or switch\");\n                semicolon();\n                return as(type, name);\n        };\n\n        function for_() {\n                expect(\"(\");\n                var init = null;\n                if (!is(\"punc\", \";\")) {\n                        init = is(\"keyword\", \"var\")\n                                ? (next(), var_(true))\n                                : expression(true, true);\n                        if (is(\"operator\", \"in\"))\n                                return for_in(init);\n                }\n                return regular_for(init);\n        };\n\n        function regular_for(init) {\n                expect(\";\");\n                var test = is(\"punc\", \";\") ? null : expression();\n                expect(\";\");\n                var step = is(\"punc\", \")\") ? null : expression();\n                expect(\")\");\n                return as(\"for\", init, test, step, in_loop(statement));\n        };\n\n        function for_in(init) {\n                var lhs = init[0] == \"var\" ? as(\"name\", init[1][0]) : init;\n                next();\n                var obj = expression();\n                expect(\")\");\n                return as(\"for-in\", init, lhs, obj, in_loop(statement));\n        };\n\n        var function_ = embed_tokens ? function() {\n                var start = prev();\n                var ast = $function_.apply(this, arguments);\n                ast[0] = add_tokens(ast[0], start, prev());\n                return ast;\n        } : $function_;\n\n        function $function_(in_statement) {\n                var name = is(\"name\") ? prog1(S.token.value, next) : null;\n                if (in_statement && !name)\n                        unexpected();\n                expect(\"(\");\n                return as(in_statement ? \"defun\" : \"function\",\n                          name,\n                          // arguments\n                          (function(first, a){\n                                  while (!is(\"punc\", \")\")) {\n                                          if (first) first = false; else expect(\",\");\n                                          if (!is(\"name\")) unexpected();\n                                          a.push(S.token.value);\n                                          next();\n                                  }\n                                  next();\n                                  return a;\n                          })(true, []),\n                          // body\n                          (function(){\n                                  ++S.in_function;\n                                  var loop = S.in_loop;\n                                  S.in_loop = 0;\n                                  var a = block_();\n                                  --S.in_function;\n                                  S.in_loop = loop;\n                                  return a;\n                          })());\n        };\n\n        function if_() {\n                var cond = parenthesised(), body = statement(), belse;\n                if (is(\"keyword\", \"else\")) {\n                        next();\n                        belse = statement();\n                }\n                return as(\"if\", cond, body, belse);\n        };\n\n        function block_() {\n                expect(\"{\");\n                var a = [];\n                while (!is(\"punc\", \"}\")) {\n                        if (is(\"eof\")) unexpected();\n                        a.push(statement());\n                }\n                next();\n                return a;\n        };\n\n        var switch_block_ = curry(in_loop, function(){\n                expect(\"{\");\n                var a = [], cur = null;\n                while (!is(\"punc\", \"}\")) {\n                        if (is(\"eof\")) unexpected();\n                        if (is(\"keyword\", \"case\")) {\n                                next();\n                                cur = [];\n                                a.push([ expression(), cur ]);\n                                expect(\":\");\n                        }\n                        else if (is(\"keyword\", \"default\")) {\n                                next();\n                                expect(\":\");\n                                cur = [];\n                                a.push([ null, cur ]);\n                        }\n                        else {\n                                if (!cur) unexpected();\n                                cur.push(statement());\n                        }\n                }\n                next();\n                return a;\n        });\n\n        function try_() {\n                var body = block_(), bcatch, bfinally;\n                if (is(\"keyword\", \"catch\")) {\n                        next();\n                        expect(\"(\");\n                        if (!is(\"name\"))\n                                croak(\"Name expected\");\n                        var name = S.token.value;\n                        next();\n                        expect(\")\");\n                        bcatch = [ name, block_() ];\n                }\n                if (is(\"keyword\", \"finally\")) {\n                        next();\n                        bfinally = block_();\n                }\n                if (!bcatch && !bfinally)\n                        croak(\"Missing catch/finally blocks\");\n                return as(\"try\", body, bcatch, bfinally);\n        };\n\n        function vardefs(no_in) {\n                var a = [];\n                for (;;) {\n                        if (!is(\"name\"))\n                                unexpected();\n                        var name = S.token.value;\n                        next();\n                        if (is(\"operator\", \"=\")) {\n                                next();\n                                a.push([ name, expression(false, no_in) ]);\n                        } else {\n                                a.push([ name ]);\n                        }\n                        if (!is(\"punc\", \",\"))\n                                break;\n                        next();\n                }\n                return a;\n        };\n\n        function var_(no_in) {\n                return as(\"var\", vardefs(no_in));\n        };\n\n        function const_() {\n                return as(\"const\", vardefs());\n        };\n\n        function new_() {\n                var newexp = expr_atom(false), args;\n                if (is(\"punc\", \"(\")) {\n                        next();\n                        args = expr_list(\")\");\n                } else {\n                        args = [];\n                }\n                return subscripts(as(\"new\", newexp, args), true);\n        };\n\n        function expr_atom(allow_calls) {\n                if (is(\"operator\", \"new\")) {\n                        next();\n                        return new_();\n                }\n                if (is(\"operator\") && HOP(UNARY_PREFIX, S.token.value)) {\n                        return make_unary(\"unary-prefix\",\n                                          prog1(S.token.value, next),\n                                          expr_atom(allow_calls));\n                }\n                if (is(\"punc\")) {\n                        switch (S.token.value) {\n                            case \"(\":\n                                next();\n                                return subscripts(prog1(expression, curry(expect, \")\")), allow_calls);\n                            case \"[\":\n                                next();\n                                return subscripts(array_(), allow_calls);\n                            case \"{\":\n                                next();\n                                return subscripts(object_(), allow_calls);\n                        }\n                        unexpected();\n                }\n                if (is(\"keyword\", \"function\")) {\n                        next();\n                        return subscripts(function_(false), allow_calls);\n                }\n                if (HOP(ATOMIC_START_TOKEN, S.token.type)) {\n                        var atom = S.token.type == \"regexp\"\n                                ? as(\"regexp\", S.token.value[0], S.token.value[1])\n                                : as(S.token.type, S.token.value);\n                        return subscripts(prog1(atom, next), allow_calls);\n                }\n                unexpected();\n        };\n\n        function expr_list(closing, allow_trailing_comma, allow_empty) {\n                var first = true, a = [];\n                while (!is(\"punc\", closing)) {\n                        if (first) first = false; else expect(\",\");\n                        if (allow_trailing_comma && is(\"punc\", closing)) break;\n                        if (is(\"punc\", \",\") && allow_empty) {\n                                a.push([ \"atom\", \"undefined\" ]);\n                        } else {\n                                a.push(expression(false));\n                        }\n                }\n                next();\n                return a;\n        };\n\n        function array_() {\n                return as(\"array\", expr_list(\"]\", !exigent_mode, true));\n        };\n\n        function object_() {\n                var first = true, a = [];\n                while (!is(\"punc\", \"}\")) {\n                        if (first) first = false; else expect(\",\");\n                        if (!exigent_mode && is(\"punc\", \"}\"))\n                                // allow trailing comma\n                                break;\n                        var type = S.token.type;\n                        var name = as_property_name();\n                        if (type == \"name\" && (name == \"get\" || name == \"set\") && !is(\"punc\", \":\")) {\n                                a.push([ as_name(), function_(false), name ]);\n                        } else {\n                                expect(\":\");\n                                a.push([ name, expression(false) ]);\n                        }\n                }\n                next();\n                return as(\"object\", a);\n        };\n\n        function as_property_name() {\n                switch (S.token.type) {\n                    case \"num\":\n                    case \"string\":\n                        return prog1(S.token.value, next);\n                }\n                return as_name();\n        };\n\n        function as_name() {\n                switch (S.token.type) {\n                    case \"name\":\n                    case \"operator\":\n                    case \"keyword\":\n                    case \"atom\":\n                        return prog1(S.token.value, next);\n                    default:\n                        unexpected();\n                }\n        };\n\n        function subscripts(expr, allow_calls) {\n                if (is(\"punc\", \".\")) {\n                        next();\n                        return subscripts(as(\"dot\", expr, as_name()), allow_calls);\n                }\n                if (is(\"punc\", \"[\")) {\n                        next();\n                        return subscripts(as(\"sub\", expr, prog1(expression, curry(expect, \"]\"))), allow_calls);\n                }\n                if (allow_calls && is(\"punc\", \"(\")) {\n                        next();\n                        return subscripts(as(\"call\", expr, expr_list(\")\")), true);\n                }\n                if (allow_calls && is(\"operator\") && HOP(UNARY_POSTFIX, S.token.value)) {\n                        return prog1(curry(make_unary, \"unary-postfix\", S.token.value, expr),\n                                     next);\n                }\n                return expr;\n        };\n\n        function make_unary(tag, op, expr) {\n                if ((op == \"++\" || op == \"--\") && !is_assignable(expr))\n                        croak(\"Invalid use of \" + op + \" operator\");\n                return as(tag, op, expr);\n        };\n\n        function expr_op(left, min_prec, no_in) {\n                var op = is(\"operator\") ? S.token.value : null;\n                if (op && op == \"in\" && no_in) op = null;\n                var prec = op != null ? PRECEDENCE[op] : null;\n                if (prec != null && prec > min_prec) {\n                        next();\n                        var right = expr_op(expr_atom(true), prec, no_in);\n                        return expr_op(as(\"binary\", op, left, right), min_prec, no_in);\n                }\n                return left;\n        };\n\n        function expr_ops(no_in) {\n                return expr_op(expr_atom(true), 0, no_in);\n        };\n\n        function maybe_conditional(no_in) {\n                var expr = expr_ops(no_in);\n                if (is(\"operator\", \"?\")) {\n                        next();\n                        var yes = expression(false);\n                        expect(\":\");\n                        return as(\"conditional\", expr, yes, expression(false, no_in));\n                }\n                return expr;\n        };\n\n        function is_assignable(expr) {\n                if (!exigent_mode) return true;\n                switch (expr[0]) {\n                    case \"dot\":\n                    case \"sub\":\n                    case \"new\":\n                    case \"call\":\n                        return true;\n                    case \"name\":\n                        return expr[1] != \"this\";\n                }\n        };\n\n        function maybe_assign(no_in) {\n                var left = maybe_conditional(no_in), val = S.token.value;\n                if (is(\"operator\") && HOP(ASSIGNMENT, val)) {\n                        if (is_assignable(left)) {\n                                next();\n                                return as(\"assign\", ASSIGNMENT[val], left, maybe_assign(no_in));\n                        }\n                        croak(\"Invalid assignment\");\n                }\n                return left;\n        };\n\n        function expression(commas, no_in) {\n                if (arguments.length == 0)\n                        commas = true;\n                var expr = maybe_assign(no_in);\n                if (commas && is(\"punc\", \",\")) {\n                        next();\n                        return as(\"seq\", expr, expression(true, no_in));\n                }\n                return expr;\n        };\n\n        function in_loop(cont) {\n                try {\n                        ++S.in_loop;\n                        return cont();\n                } finally {\n                        --S.in_loop;\n                }\n        };\n\n        return as(\"toplevel\", (function(a){\n                while (!is(\"eof\"))\n                        a.push(statement());\n                return a;\n        })([]));\n\n};\n\n/* -----[ Utilities ]----- */\n\nfunction curry(f) {\n        var args = slice(arguments, 1);\n        return function() { return f.apply(this, args.concat(slice(arguments))); };\n};\n\nfunction prog1(ret) {\n        if (ret instanceof Function)\n                ret = ret();\n        for (var i = 1, n = arguments.length; --n > 0; ++i)\n                arguments[i]();\n        return ret;\n};\n\nfunction array_to_hash(a) {\n        var ret = {};\n        for (var i = 0; i < a.length; ++i)\n                ret[a[i]] = true;\n        return ret;\n};\n\nfunction slice(a, start) {\n        return Array.prototype.slice.call(a, start == null ? 0 : start);\n};\n\nfunction characters(str) {\n        return str.split(\"\");\n};\n\nfunction member(name, array) {\n        for (var i = array.length; --i >= 0;)\n                if (array[i] === name)\n                        return true;\n        return false;\n};\n\nfunction HOP(obj, prop) {\n        return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\nvar warn = function() {};\n\n/* -----[ Exports ]----- */\n\nexports.tokenizer = tokenizer;\nexports.parse = parse;\nexports.slice = slice;\nexports.curry = curry;\nexports.member = member;\nexports.array_to_hash = array_to_hash;\nexports.PRECEDENCE = PRECEDENCE;\nexports.KEYWORDS_ATOM = KEYWORDS_ATOM;\nexports.RESERVED_WORDS = RESERVED_WORDS;\nexports.KEYWORDS = KEYWORDS;\nexports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;\nexports.OPERATORS = OPERATORS;\nexports.is_alphanumeric_char = is_alphanumeric_char;\nexports.set_logger = function(logger) {\n        warn = logger;\n};\n"
  },
  {
    "path": "build/lib/process.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n\n  This version is suitable for Node.js.  With minimal changes (the\n  exports stuff) it should work on any JS platform.\n\n  This file implements some AST processors.  They work on data built\n  by parse-js.\n\n  Exported functions:\n\n    - ast_mangle(ast, options) -- mangles the variable/function names\n      in the AST.  Returns an AST.\n\n    - ast_squeeze(ast) -- employs various optimizations to make the\n      final generated code even smaller.  Returns an AST.\n\n    - gen_code(ast, options) -- generates JS code from the AST.  Pass\n      true (or an object, see the code for some options) as second\n      argument to get \"pretty\" (indented) code.\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\nvar jsp = require(\"./parse-js\"),\n    slice = jsp.slice,\n    member = jsp.member,\n    PRECEDENCE = jsp.PRECEDENCE,\n    OPERATORS = jsp.OPERATORS;\n\n/* -----[ helper for AST traversal ]----- */\n\nfunction ast_walker(ast) {\n        function _vardefs(defs) {\n                return [ this[0], MAP(defs, function(def){\n                        var a = [ def[0] ];\n                        if (def.length > 1)\n                                a[1] = walk(def[1]);\n                        return a;\n                }) ];\n        };\n        var walkers = {\n                \"string\": function(str) {\n                        return [ this[0], str ];\n                },\n                \"num\": function(num) {\n                        return [ this[0], num ];\n                },\n                \"name\": function(name) {\n                        return [ this[0], name ];\n                },\n                \"toplevel\": function(statements) {\n                        return [ this[0], MAP(statements, walk) ];\n                },\n                \"block\": function(statements) {\n                        var out = [ this[0] ];\n                        if (statements != null)\n                                out.push(MAP(statements, walk));\n                        return out;\n                },\n                \"var\": _vardefs,\n                \"const\": _vardefs,\n                \"try\": function(t, c, f) {\n                        return [\n                                this[0],\n                                MAP(t, walk),\n                                c != null ? [ c[0], MAP(c[1], walk) ] : null,\n                                f != null ? MAP(f, walk) : null\n                        ];\n                },\n                \"throw\": function(expr) {\n                        return [ this[0], walk(expr) ];\n                },\n                \"new\": function(ctor, args) {\n                        return [ this[0], walk(ctor), MAP(args, walk) ];\n                },\n                \"switch\": function(expr, body) {\n                        return [ this[0], walk(expr), MAP(body, function(branch){\n                                return [ branch[0] ? walk(branch[0]) : null,\n                                         MAP(branch[1], walk) ];\n                        }) ];\n                },\n                \"break\": function(label) {\n                        return [ this[0], label ];\n                },\n                \"continue\": function(label) {\n                        return [ this[0], label ];\n                },\n                \"conditional\": function(cond, t, e) {\n                        return [ this[0], walk(cond), walk(t), walk(e) ];\n                },\n                \"assign\": function(op, lvalue, rvalue) {\n                        return [ this[0], op, walk(lvalue), walk(rvalue) ];\n                },\n                \"dot\": function(expr) {\n                        return [ this[0], walk(expr) ].concat(slice(arguments, 1));\n                },\n                \"call\": function(expr, args) {\n                        return [ this[0], walk(expr), MAP(args, walk) ];\n                },\n                \"function\": function(name, args, body) {\n                        return [ this[0], name, args.slice(), MAP(body, walk) ];\n                },\n                \"defun\": function(name, args, body) {\n                        return [ this[0], name, args.slice(), MAP(body, walk) ];\n                },\n                \"if\": function(conditional, t, e) {\n                        return [ this[0], walk(conditional), walk(t), walk(e) ];\n                },\n                \"for\": function(init, cond, step, block) {\n                        return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];\n                },\n                \"for-in\": function(vvar, key, hash, block) {\n                        return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];\n                },\n                \"while\": function(cond, block) {\n                        return [ this[0], walk(cond), walk(block) ];\n                },\n                \"do\": function(cond, block) {\n                        return [ this[0], walk(cond), walk(block) ];\n                },\n                \"return\": function(expr) {\n                        return [ this[0], walk(expr) ];\n                },\n                \"binary\": function(op, left, right) {\n                        return [ this[0], op, walk(left), walk(right) ];\n                },\n                \"unary-prefix\": function(op, expr) {\n                        return [ this[0], op, walk(expr) ];\n                },\n                \"unary-postfix\": function(op, expr) {\n                        return [ this[0], op, walk(expr) ];\n                },\n                \"sub\": function(expr, subscript) {\n                        return [ this[0], walk(expr), walk(subscript) ];\n                },\n                \"object\": function(props) {\n                        return [ this[0], MAP(props, function(p){\n                                return p.length == 2\n                                        ? [ p[0], walk(p[1]) ]\n                                        : [ p[0], walk(p[1]), p[2] ]; // get/set-ter\n                        }) ];\n                },\n                \"regexp\": function(rx, mods) {\n                        return [ this[0], rx, mods ];\n                },\n                \"array\": function(elements) {\n                        return [ this[0], MAP(elements, walk) ];\n                },\n                \"stat\": function(stat) {\n                        return [ this[0], walk(stat) ];\n                },\n                \"seq\": function() {\n                        return [ this[0] ].concat(MAP(slice(arguments), walk));\n                },\n                \"label\": function(name, block) {\n                        return [ this[0], name, walk(block) ];\n                },\n                \"with\": function(expr, block) {\n                        return [ this[0], walk(expr), walk(block) ];\n                },\n                \"atom\": function(name) {\n                        return [ this[0], name ];\n                }\n        };\n\n        var user = {};\n        var stack = [];\n        function walk(ast) {\n                if (ast == null)\n                        return null;\n                try {\n                        stack.push(ast);\n                        var type = ast[0];\n                        var gen = user[type];\n                        if (gen) {\n                                var ret = gen.apply(ast, ast.slice(1));\n                                if (ret != null)\n                                        return ret;\n                        }\n                        gen = walkers[type];\n                        return gen.apply(ast, ast.slice(1));\n                } finally {\n                        stack.pop();\n                }\n        };\n\n        function with_walkers(walkers, cont){\n                var save = {}, i;\n                for (i in walkers) if (HOP(walkers, i)) {\n                        save[i] = user[i];\n                        user[i] = walkers[i];\n                }\n                var ret = cont();\n                for (i in save) if (HOP(save, i)) {\n                        if (!save[i]) delete user[i];\n                        else user[i] = save[i];\n                }\n                return ret;\n        };\n\n        return {\n                walk: walk,\n                with_walkers: with_walkers,\n                parent: function() {\n                        return stack[stack.length - 2]; // last one is current node\n                },\n                stack: function() {\n                        return stack;\n                }\n        };\n};\n\n/* -----[ Scope and mangling ]----- */\n\nfunction Scope(parent) {\n        this.names = {};        // names defined in this scope\n        this.mangled = {};      // mangled names (orig.name => mangled)\n        this.rev_mangled = {};  // reverse lookup (mangled => orig.name)\n        this.cname = -1;        // current mangled name\n        this.refs = {};         // names referenced from this scope\n        this.uses_with = false; // will become TRUE if eval() is detected in this or any subscopes\n        this.uses_eval = false; // will become TRUE if with() is detected in this or any subscopes\n        this.parent = parent;   // parent scope\n        this.children = [];     // sub-scopes\n        if (parent) {\n                this.level = parent.level + 1;\n                parent.children.push(this);\n        } else {\n                this.level = 0;\n        }\n};\n\nvar base54 = (function(){\n        var DIGITS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_\";\n        return function(num) {\n                var ret = \"\";\n                do {\n                        ret = DIGITS.charAt(num % 54) + ret;\n                        num = Math.floor(num / 54);\n                } while (num > 0);\n                return ret;\n        };\n})();\n\nScope.prototype = {\n        has: function(name) {\n                for (var s = this; s; s = s.parent)\n                        if (HOP(s.names, name))\n                                return s;\n        },\n        has_mangled: function(mname) {\n                for (var s = this; s; s = s.parent)\n                        if (HOP(s.rev_mangled, mname))\n                                return s;\n        },\n        toJSON: function() {\n                return {\n                        names: this.names,\n                        uses_eval: this.uses_eval,\n                        uses_with: this.uses_with\n                };\n        },\n\n        next_mangled: function() {\n                // we must be careful that the new mangled name:\n                //\n                // 1. doesn't shadow a mangled name from a parent\n                //    scope, unless we don't reference the original\n                //    name from this scope OR from any sub-scopes!\n                //    This will get slow.\n                //\n                // 2. doesn't shadow an original name from a parent\n                //    scope, in the event that the name is not mangled\n                //    in the parent scope and we reference that name\n                //    here OR IN ANY SUBSCOPES!\n                //\n                // 3. doesn't shadow a name that is referenced but not\n                //    defined (possibly global defined elsewhere).\n                for (;;) {\n                        var m = base54(++this.cname), prior;\n\n                        // case 1.\n                        prior = this.has_mangled(m);\n                        if (prior && this.refs[prior.rev_mangled[m]] === prior)\n                                continue;\n\n                        // case 2.\n                        prior = this.has(m);\n                        if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))\n                                continue;\n\n                        // case 3.\n                        if (HOP(this.refs, m) && this.refs[m] == null)\n                                continue;\n\n                        // I got \"do\" once. :-/\n                        if (!is_identifier(m))\n                                continue;\n\n                        return m;\n                }\n        },\n        get_mangled: function(name, newMangle) {\n                if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use\n                var s = this.has(name);\n                if (!s) return name; // not in visible scope, no mangle\n                if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope\n                if (!newMangle) return name;                      // not found and no mangling requested\n\n                var m = s.next_mangled();\n                s.rev_mangled[m] = name;\n                return s.mangled[name] = m;\n        },\n        define: function(name) {\n                if (name != null)\n                        return this.names[name] = name;\n        }\n};\n\nfunction ast_add_scope(ast) {\n\n        var current_scope = null;\n        var w = ast_walker(), walk = w.walk;\n        var having_eval = [];\n\n        function with_new_scope(cont) {\n                current_scope = new Scope(current_scope);\n                var ret = current_scope.body = cont();\n                ret.scope = current_scope;\n                current_scope = current_scope.parent;\n                return ret;\n        };\n\n        function define(name) {\n                return current_scope.define(name);\n        };\n\n        function reference(name) {\n                current_scope.refs[name] = true;\n        };\n\n        function _lambda(name, args, body) {\n                return [ this[0], define(name), args, with_new_scope(function(){\n                        MAP(args, define);\n                        return MAP(body, walk);\n                })];\n        };\n\n        return with_new_scope(function(){\n                // process AST\n                var ret = w.with_walkers({\n                        \"function\": _lambda,\n                        \"defun\": _lambda,\n                        \"with\": function(expr, block) {\n                                for (var s = current_scope; s; s = s.parent)\n                                        s.uses_with = true;\n                        },\n                        \"var\": function(defs) {\n                                MAP(defs, function(d){ define(d[0]) });\n                        },\n                        \"const\": function(defs) {\n                                MAP(defs, function(d){ define(d[0]) });\n                        },\n                        \"try\": function(t, c, f) {\n                                if (c != null) return [\n                                        this[0],\n                                        MAP(t, walk),\n                                        [ define(c[0]), MAP(c[1], walk) ],\n                                        f != null ? MAP(f, walk) : null\n                                ];\n                        },\n                        \"name\": function(name) {\n                                if (name == \"eval\")\n                                        having_eval.push(current_scope);\n                                reference(name);\n                        }\n                }, function(){\n                        return walk(ast);\n                });\n\n                // the reason why we need an additional pass here is\n                // that names can be used prior to their definition.\n\n                // scopes where eval was detected and their parents\n                // are marked with uses_eval, unless they define the\n                // \"eval\" name.\n                MAP(having_eval, function(scope){\n                        if (!scope.has(\"eval\")) while (scope) {\n                                scope.uses_eval = true;\n                                scope = scope.parent;\n                        }\n                });\n\n                // for referenced names it might be useful to know\n                // their origin scope.  current_scope here is the\n                // toplevel one.\n                function fixrefs(scope, i) {\n                        // do children first; order shouldn't matter\n                        for (i = scope.children.length; --i >= 0;)\n                                fixrefs(scope.children[i]);\n                        for (i in scope.refs) if (HOP(scope.refs, i)) {\n                                // find origin scope and propagate the reference to origin\n                                for (var origin = scope.has(i), s = scope; s; s = s.parent) {\n                                        s.refs[i] = origin;\n                                        if (s === origin) break;\n                                }\n                        }\n                };\n                fixrefs(current_scope);\n\n                return ret;\n        });\n\n};\n\n/* -----[ mangle names ]----- */\n\nfunction ast_mangle(ast, options) {\n        var w = ast_walker(), walk = w.walk, scope;\n        options = options || {};\n\n        function get_mangled(name, newMangle) {\n                if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel\n                if (options.except && member(name, options.except))\n                        return name;\n                return scope.get_mangled(name, newMangle);\n        };\n\n        function _lambda(name, args, body) {\n                if (name) name = get_mangled(name);\n                body = with_scope(body.scope, function(){\n                        args = MAP(args, function(name){ return get_mangled(name) });\n                        return MAP(body, walk);\n                });\n                return [ this[0], name, args, body ];\n        };\n\n        function with_scope(s, cont) {\n                var _scope = scope;\n                scope = s;\n                for (var i in s.names) if (HOP(s.names, i)) {\n                        get_mangled(i, true);\n                }\n                var ret = cont();\n                ret.scope = s;\n                scope = _scope;\n                return ret;\n        };\n\n        function _vardefs(defs) {\n                return [ this[0], MAP(defs, function(d){\n                        return [ get_mangled(d[0]), walk(d[1]) ];\n                }) ];\n        };\n\n        return w.with_walkers({\n                \"function\": _lambda,\n                \"defun\": function() {\n                        // move function declarations to the top when\n                        // they are not in some block.\n                        var ast = _lambda.apply(this, arguments);\n                        switch (w.parent()[0]) {\n                            case \"toplevel\":\n                            case \"function\":\n                            case \"defun\":\n                                return MAP.at_top(ast);\n                        }\n                        return ast;\n                },\n                \"var\": _vardefs,\n                \"const\": _vardefs,\n                \"name\": function(name) {\n                        return [ this[0], get_mangled(name) ];\n                },\n                \"try\": function(t, c, f) {\n                        return [ this[0],\n                                 MAP(t, walk),\n                                 c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,\n                                 f != null ? MAP(f, walk) : null ];\n                },\n                \"toplevel\": function(body) {\n                        var self = this;\n                        return with_scope(self.scope, function(){\n                                return [ self[0], MAP(body, walk) ];\n                        });\n                }\n        }, function() {\n                return walk(ast_add_scope(ast));\n        });\n};\n\n/* -----[\n   - compress foo[\"bar\"] into foo.bar,\n   - remove block brackets {} where possible\n   - join consecutive var declarations\n   - various optimizations for IFs:\n     - if (cond) foo(); else bar();  ==>  cond?foo():bar();\n     - if (cond) foo();  ==>  cond&&foo();\n     - if (foo) return bar(); else return baz();  ==> return foo?bar():baz(); // also for throw\n     - if (foo) return bar(); else something();  ==> {if(foo)return bar();something()}\n   ]----- */\n\nvar warn = function(){};\n\nfunction best_of(ast1, ast2) {\n        return gen_code(ast1).length > gen_code(ast2[0] == \"stat\" ? ast2[1] : ast2).length ? ast2 : ast1;\n};\n\nfunction last_stat(b) {\n        if (b[0] == \"block\" && b[1] && b[1].length > 0)\n                return b[1][b[1].length - 1];\n        return b;\n}\n\nfunction aborts(t) {\n        if (t) {\n                t = last_stat(t);\n                if (t[0] == \"return\" || t[0] == \"break\" || t[0] == \"continue\" || t[0] == \"throw\")\n                        return true;\n        }\n};\n\nfunction boolean_expr(expr) {\n        return ( (expr[0] == \"unary-prefix\"\n                  && member(expr[1], [ \"!\", \"delete\" ])) ||\n\n                 (expr[0] == \"binary\"\n                  && member(expr[1], [ \"in\", \"instanceof\", \"==\", \"!=\", \"===\", \"!==\", \"<\", \"<=\", \">=\", \">\" ])) ||\n\n                 (expr[0] == \"binary\"\n                  && member(expr[1], [ \"&&\", \"||\" ])\n                  && boolean_expr(expr[2])\n                  && boolean_expr(expr[3])) ||\n\n                 (expr[0] == \"conditional\"\n                  && boolean_expr(expr[2])\n                  && boolean_expr(expr[3])) ||\n\n                 (expr[0] == \"assign\"\n                  && expr[1] === true\n                  && boolean_expr(expr[3])) ||\n\n                 (expr[0] == \"seq\"\n                  && boolean_expr(expr[expr.length - 1]))\n               );\n};\n\nfunction make_conditional(c, t, e) {\n        if (c[0] == \"unary-prefix\" && c[1] == \"!\") {\n                return e ? [ \"conditional\", c[2], e, t ] : [ \"binary\", \"||\", c[2], t ];\n        } else {\n                return e ? [ \"conditional\", c, t, e ] : [ \"binary\", \"&&\", c, t ];\n        }\n};\n\nfunction empty(b) {\n        return !b || (b[0] == \"block\" && (!b[1] || b[1].length == 0));\n};\n\nfunction is_string(node) {\n        return (node[0] == \"string\" ||\n                node[0] == \"unary-prefix\" && node[1] == \"typeof\" ||\n                node[0] == \"binary\" && node[1] == \"+\" &&\n                (is_string(node[2]) || is_string(node[3])));\n};\n\nvar when_constant = (function(){\n\n        var $NOT_CONSTANT = {};\n\n        // this can only evaluate constant expressions.  If it finds anything\n        // not constant, it throws $NOT_CONSTANT.\n        function evaluate(expr) {\n                switch (expr[0]) {\n                    case \"string\":\n                    case \"num\":\n                        return expr[1];\n                    case \"name\":\n                    case \"atom\":\n                        switch (expr[1]) {\n                            case \"true\": return true;\n                            case \"false\": return false;\n                        }\n                        break;\n                    case \"unary-prefix\":\n                        switch (expr[1]) {\n                            case \"!\": return !evaluate(expr[2]);\n                            case \"typeof\": return typeof evaluate(expr[2]);\n                            case \"~\": return ~evaluate(expr[2]);\n                            case \"-\": return -evaluate(expr[2]);\n                            case \"+\": return +evaluate(expr[2]);\n                        }\n                        break;\n                    case \"binary\":\n                        var left = expr[2], right = expr[3];\n                        switch (expr[1]) {\n                            case \"&&\"         : return evaluate(left) &&         evaluate(right);\n                            case \"||\"         : return evaluate(left) ||         evaluate(right);\n                            case \"|\"          : return evaluate(left) |          evaluate(right);\n                            case \"&\"          : return evaluate(left) &          evaluate(right);\n                            case \"^\"          : return evaluate(left) ^          evaluate(right);\n                            case \"+\"          : return evaluate(left) +          evaluate(right);\n                            case \"*\"          : return evaluate(left) *          evaluate(right);\n                            case \"/\"          : return evaluate(left) /          evaluate(right);\n                            case \"-\"          : return evaluate(left) -          evaluate(right);\n                            case \"<<\"         : return evaluate(left) <<         evaluate(right);\n                            case \">>\"         : return evaluate(left) >>         evaluate(right);\n                            case \">>>\"        : return evaluate(left) >>>        evaluate(right);\n                            case \"==\"         : return evaluate(left) ==         evaluate(right);\n                            case \"===\"        : return evaluate(left) ===        evaluate(right);\n                            case \"!=\"         : return evaluate(left) !=         evaluate(right);\n                            case \"!==\"        : return evaluate(left) !==        evaluate(right);\n                            case \"<\"          : return evaluate(left) <          evaluate(right);\n                            case \"<=\"         : return evaluate(left) <=         evaluate(right);\n                            case \">\"          : return evaluate(left) >          evaluate(right);\n                            case \">=\"         : return evaluate(left) >=         evaluate(right);\n                            case \"in\"         : return evaluate(left) in         evaluate(right);\n                            case \"instanceof\" : return evaluate(left) instanceof evaluate(right);\n                        }\n                }\n                throw $NOT_CONSTANT;\n        };\n\n        return function(expr, yes, no) {\n                try {\n                        var val = evaluate(expr), ast;\n                        switch (typeof val) {\n                            case \"string\": ast =  [ \"string\", val ]; break;\n                            case \"number\": ast =  [ \"num\", val ]; break;\n                            case \"boolean\": ast =  [ \"name\", String(val) ]; break;\n                            default: throw new Error(\"Can't handle constant of type: \" + (typeof val));\n                        }\n                        return yes.call(expr, ast, val);\n                } catch(ex) {\n                        if (ex === $NOT_CONSTANT) {\n                                if (expr[0] == \"binary\"\n                                    && (expr[1] == \"===\" || expr[1] == \"!==\")\n                                    && ((is_string(expr[2]) && is_string(expr[3]))\n                                        || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {\n                                        expr[1] = expr[1].substr(0, 2);\n                                }\n                                return no ? no.call(expr, expr) : null;\n                        }\n                        else throw ex;\n                }\n        };\n\n})();\n\nfunction warn_unreachable(ast) {\n        if (!empty(ast))\n                warn(\"Dropping unreachable code: \" + gen_code(ast, true));\n};\n\nfunction ast_squeeze(ast, options) {\n        options = defaults(options, {\n                make_seqs   : true,\n                dead_code   : true,\n                keep_comps  : true,\n                no_warnings : false\n        });\n\n        var w = ast_walker(), walk = w.walk, scope;\n\n        function negate(c) {\n                var not_c = [ \"unary-prefix\", \"!\", c ];\n                switch (c[0]) {\n                    case \"unary-prefix\":\n                        return c[1] == \"!\" && boolean_expr(c[2]) ? c[2] : not_c;\n                    case \"seq\":\n                        c = slice(c);\n                        c[c.length - 1] = negate(c[c.length - 1]);\n                        return c;\n                    case \"conditional\":\n                        return best_of(not_c, [ \"conditional\", c[1], negate(c[2]), negate(c[3]) ]);\n                    case \"binary\":\n                        var op = c[1], left = c[2], right = c[3];\n                        if (!options.keep_comps) switch (op) {\n                            case \"<=\"  : return [ \"binary\", \">\", left, right ];\n                            case \"<\"   : return [ \"binary\", \">=\", left, right ];\n                            case \">=\"  : return [ \"binary\", \"<\", left, right ];\n                            case \">\"   : return [ \"binary\", \"<=\", left, right ];\n                        }\n                        switch (op) {\n                            case \"==\"  : return [ \"binary\", \"!=\", left, right ];\n                            case \"!=\"  : return [ \"binary\", \"==\", left, right ];\n                            case \"===\" : return [ \"binary\", \"!==\", left, right ];\n                            case \"!==\" : return [ \"binary\", \"===\", left, right ];\n                            case \"&&\"  : return best_of(not_c, [ \"binary\", \"||\", negate(left), negate(right) ]);\n                            case \"||\"  : return best_of(not_c, [ \"binary\", \"&&\", negate(left), negate(right) ]);\n                        }\n                        break;\n                }\n                return not_c;\n        };\n\n        function with_scope(s, cont) {\n                var _scope = scope;\n                scope = s;\n                var ret = cont();\n                ret.scope = s;\n                scope = _scope;\n                return ret;\n        };\n\n        function rmblock(block) {\n                if (block != null && block[0] == \"block\" && block[1]) {\n                        if (block[1].length == 1)\n                                block = block[1][0];\n                        else if (block[1].length == 0)\n                                block = [ \"block\" ];\n                }\n                return block;\n        };\n\n        function _lambda(name, args, body) {\n                return [ this[0], name, args, with_scope(body.scope, function(){\n                        return tighten(MAP(body, walk), \"lambda\");\n                }) ];\n        };\n\n        // we get here for blocks that have been already transformed.\n        // this function does a few things:\n        // 1. discard useless blocks\n        // 2. join consecutive var declarations\n        // 3. remove obviously dead code\n        // 4. transform consecutive statements using the comma operator\n        // 5. if block_type == \"lambda\" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }\n        function tighten(statements, block_type) {\n                statements = statements.reduce(function(a, stat){\n                        if (stat[0] == \"block\") {\n                                if (stat[1]) {\n                                        a.push.apply(a, stat[1]);\n                                }\n                        } else {\n                                a.push(stat);\n                        }\n                        return a;\n                }, []);\n\n                statements = (function(a, prev){\n                        statements.forEach(function(cur){\n                                if (prev && ((cur[0] == \"var\" && prev[0] == \"var\") ||\n                                             (cur[0] == \"const\" && prev[0] == \"const\"))) {\n                                        prev[1] = prev[1].concat(cur[1]);\n                                } else {\n                                        a.push(cur);\n                                        prev = cur;\n                                }\n                        });\n                        return a;\n                })([]);\n\n                if (options.dead_code) statements = (function(a, has_quit){\n                        statements.forEach(function(st){\n                                if (has_quit) {\n                                        if (member(st[0], [ \"function\", \"defun\" , \"var\", \"const\" ])) {\n                                                a.push(st);\n                                        }\n                                        else if (!options.no_warnings)\n                                                warn_unreachable(st);\n                                }\n                                else {\n                                        a.push(st);\n                                        if (member(st[0], [ \"return\", \"throw\", \"break\", \"continue\" ]))\n                                                has_quit = true;\n                                }\n                        });\n                        return a;\n                })([]);\n\n                if (options.make_seqs) statements = (function(a, prev) {\n                        statements.forEach(function(cur){\n                                if (prev && prev[0] == \"stat\" && cur[0] == \"stat\") {\n                                        prev[1] = [ \"seq\", prev[1], cur[1] ];\n                                } else {\n                                        a.push(cur);\n                                        prev = cur;\n                                }\n                        });\n                        return a;\n                })([]);\n\n                if (block_type == \"lambda\") statements = (function(i, a, stat){\n                        while (i < statements.length) {\n                                stat = statements[i++];\n                                if (stat[0] == \"if\" && !stat[3]) {\n                                        if (stat[2][0] == \"return\" && stat[2][1] == null) {\n                                                a.push(make_if(negate(stat[1]), [ \"block\", statements.slice(i) ]));\n                                                break;\n                                        }\n                                        var last = last_stat(stat[2]);\n                                        if (last[0] == \"return\" && last[1] == null) {\n                                                a.push(make_if(stat[1], [ \"block\", stat[2][1].slice(0, -1) ], [ \"block\", statements.slice(i) ]));\n                                                break;\n                                        }\n                                }\n                                a.push(stat);\n                        }\n                        return a;\n                })(0, []);\n\n                return statements;\n        };\n\n        function make_if(c, t, e) {\n                return when_constant(c, function(ast, val){\n                        if (val) {\n                                warn_unreachable(e);\n                                return t;\n                        } else {\n                                warn_unreachable(t);\n                                return e;\n                        }\n                }, function() {\n                        return make_real_if(c, t, e);\n                });\n        };\n\n        function make_real_if(c, t, e) {\n                c = walk(c);\n                t = walk(t);\n                e = walk(e);\n\n                if (empty(t)) {\n                        c = negate(c);\n                        t = e;\n                        e = null;\n                } else if (empty(e)) {\n                        e = null;\n                } else {\n                        // if we have both else and then, maybe it makes sense to switch them?\n                        (function(){\n                                var a = gen_code(c);\n                                var n = negate(c);\n                                var b = gen_code(n);\n                                if (b.length < a.length) {\n                                        var tmp = t;\n                                        t = e;\n                                        e = tmp;\n                                        c = n;\n                                }\n                        })();\n                }\n                if (empty(e) && empty(t))\n                        return [ \"stat\", c ];\n                var ret = [ \"if\", c, t, e ];\n                if (t[0] == \"if\" && empty(t[3]) && empty(e)) {\n                        ret = best_of(ret, walk([ \"if\", [ \"binary\", \"&&\", c, t[1] ], t[2] ]));\n                }\n                else if (t[0] == \"stat\") {\n                        if (e) {\n                                if (e[0] == \"stat\") {\n                                        ret = best_of(ret, [ \"stat\", make_conditional(c, t[1], e[1]) ]);\n                                }\n                        }\n                        else {\n                                ret = best_of(ret, [ \"stat\", make_conditional(c, t[1]) ]);\n                        }\n                }\n                else if (e && t[0] == e[0] && (t[0] == \"return\" || t[0] == \"throw\") && t[1] && e[1]) {\n                        ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);\n                }\n                else if (e && aborts(t)) {\n                        ret = [ [ \"if\", c, t ] ];\n                        if (e[0] == \"block\") {\n                                if (e[1]) ret = ret.concat(e[1]);\n                        }\n                        else {\n                                ret.push(e);\n                        }\n                        ret = walk([ \"block\", ret ]);\n                }\n                else if (t && aborts(e)) {\n                        ret = [ [ \"if\", negate(c), e ] ];\n                        if (t[0] == \"block\") {\n                                if (t[1]) ret = ret.concat(t[1]);\n                        } else {\n                                ret.push(t);\n                        }\n                        ret = walk([ \"block\", ret ]);\n                }\n                return ret;\n        };\n\n        function _do_while(cond, body) {\n                return when_constant(cond, function(cond, val){\n                        if (!val) {\n                                warn_unreachable(body);\n                                return [ \"block\" ];\n                        } else {\n                                return [ \"for\", null, null, null, walk(body) ];\n                        }\n                });\n        };\n\n        return w.with_walkers({\n                \"sub\": function(expr, subscript) {\n                        if (subscript[0] == \"string\") {\n                                var name = subscript[1];\n                                if (is_identifier(name)) {\n                                        return [ \"dot\", walk(expr), name ];\n                                }\n                        }\n                },\n                \"if\": make_if,\n                \"toplevel\": function(body) {\n                        return [ \"toplevel\", with_scope(this.scope, function(){\n                                return tighten(MAP(body, walk));\n                        }) ];\n                },\n                \"switch\": function(expr, body) {\n                        var last = body.length - 1;\n                        return [ \"switch\", walk(expr), MAP(body, function(branch, i){\n                                var block = tighten(MAP(branch[1], walk));\n                                if (i == last && block.length > 0) {\n                                        var node = block[block.length - 1];\n                                        if (node[0] == \"break\" && !node[1])\n                                                block.pop();\n                                }\n                                return [ branch[0] ? walk(branch[0]) : null, block ];\n                        }) ];\n                },\n                \"function\": function() {\n                        var ret = _lambda.apply(this, arguments);\n                        if (ret[1] && !HOP(scope.refs, ret[1])) {\n                                ret[1] = null;\n                        }\n                        return ret;\n                },\n                \"defun\": _lambda,\n                \"block\": function(body) {\n                        if (body) return rmblock([ \"block\", tighten(MAP(body, walk)) ]);\n                },\n                \"binary\": function(op, left, right) {\n                        return when_constant([ \"binary\", op, walk(left), walk(right) ], function yes(c){\n                                return best_of(walk(c), this);\n                        }, function no() {\n                                return this;\n                        });\n                },\n                \"conditional\": function(c, t, e) {\n                        return make_conditional(walk(c), walk(t), walk(e));\n                },\n                \"try\": function(t, c, f) {\n                        return [\n                                \"try\",\n                                tighten(MAP(t, walk)),\n                                c != null ? [ c[0], tighten(MAP(c[1], walk)) ] : null,\n                                f != null ? tighten(MAP(f, walk)) : null\n                        ];\n                },\n                \"unary-prefix\": function(op, expr) {\n                        expr = walk(expr);\n                        var ret = [ \"unary-prefix\", op, expr ];\n                        if (op == \"!\")\n                                ret = best_of(ret, negate(expr));\n                        return when_constant(ret, function(ast, val){\n                                return walk(ast); // it's either true or false, so minifies to !0 or !1\n                        }, function() { return ret });\n                },\n                \"name\": function(name) {\n                        switch (name) {\n                            case \"true\": return [ \"unary-prefix\", \"!\", [ \"num\", 0 ]];\n                            case \"false\": return [ \"unary-prefix\", \"!\", [ \"num\", 1 ]];\n                        }\n                },\n                \"new\": function(ctor, args) {\n                        if (ctor[0] == \"name\" && ctor[1] == \"Array\" && !scope.has(\"Array\")) {\n                                if (args.length != 1) {\n                                        return [ \"array\", args ];\n                                } else {\n                                        return [ \"call\", [ \"name\", \"Array\" ], args ];\n                                }\n                        }\n                },\n                \"call\": function(expr, args) {\n                        if (expr[0] == \"name\" && expr[1] == \"Array\" && args.length != 1 && !scope.has(\"Array\")) {\n                                return [ \"array\", args ];\n                        }\n                },\n                \"while\": _do_while,\n                \"do\": _do_while\n        }, function() {\n                return walk(ast_add_scope(ast));\n        });\n};\n\n/* -----[ re-generate code from the AST ]----- */\n\nvar DOT_CALL_NO_PARENS = jsp.array_to_hash([\n        \"name\",\n        \"array\",\n        \"string\",\n        \"dot\",\n        \"sub\",\n        \"call\",\n        \"regexp\"\n]);\n\nfunction make_string(str, ascii_only) {\n        var dq = 0, sq = 0;\n        str = str.replace(/[\\\\\\b\\f\\n\\r\\t\\x22\\x27]/g, function(s){\n                switch (s) {\n                    case \"\\\\\": return \"\\\\\\\\\";\n                    case \"\\b\": return \"\\\\b\";\n                    case \"\\f\": return \"\\\\f\";\n                    case \"\\n\": return \"\\\\n\";\n                    case \"\\r\": return \"\\\\r\";\n                    case \"\\t\": return \"\\\\t\";\n                    case '\"': ++dq; return '\"';\n                    case \"'\": ++sq; return \"'\";\n                }\n                return s;\n        });\n        if (ascii_only) str = to_ascii(str);\n        if (dq > sq) return \"'\" + str.replace(/\\x27/g, \"\\\\'\") + \"'\";\n        else return '\"' + str.replace(/\\x22/g, '\\\\\"') + '\"';\n};\n\nfunction to_ascii(str) {\n        return str.replace(/[\\u0080-\\uffff]/g, function(ch) {\n                var code = ch.charCodeAt(0).toString(16);\n                while (code.length < 4) code = \"0\" + code;\n                return \"\\\\u\" + code;\n        });\n};\n\nfunction gen_code(ast, options) {\n        options = defaults(options, {\n                indent_start : 0,\n                indent_level : 4,\n                quote_keys   : false,\n                space_colon  : false,\n                beautify     : false,\n                ascii_only   : false\n        });\n        var beautify = !!options.beautify;\n        var indentation = 0,\n            newline = beautify ? \"\\n\" : \"\",\n            space = beautify ? \" \" : \"\";\n\n        function encode_string(str) {\n                return make_string(str, options.ascii_only);\n        };\n\n        function make_name(name) {\n                name = name.toString();\n                if (options.ascii_only)\n                        name = to_ascii(name);\n                return name;\n        };\n\n        function indent(line) {\n                if (line == null)\n                        line = \"\";\n                if (beautify)\n                        line = repeat_string(\" \", options.indent_start + indentation * options.indent_level) + line;\n                return line;\n        };\n\n        function with_indent(cont, incr) {\n                if (incr == null) incr = 1;\n                indentation += incr;\n                try { return cont.apply(null, slice(arguments, 1)); }\n                finally { indentation -= incr; }\n        };\n\n        function add_spaces(a) {\n                if (beautify)\n                        return a.join(\" \");\n                var b = [];\n                for (var i = 0; i < a.length; ++i) {\n                        var next = a[i + 1];\n                        b.push(a[i]);\n                        if (next &&\n                            ((/[a-z0-9_\\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\\x24]/i.test(next.toString())) ||\n                             (/[\\+\\-]$/.test(a[i].toString()) && /^[\\+\\-]/.test(next.toString())))) {\n                                b.push(\" \");\n                        }\n                }\n                return b.join(\"\");\n        };\n\n        function add_commas(a) {\n                return a.join(\",\" + space);\n        };\n\n        function parenthesize(expr) {\n                var gen = make(expr);\n                for (var i = 1; i < arguments.length; ++i) {\n                        var el = arguments[i];\n                        if ((el instanceof Function && el(expr)) || expr[0] == el)\n                                return \"(\" + gen + \")\";\n                }\n                return gen;\n        };\n\n        function best_of(a) {\n                if (a.length == 1) {\n                        return a[0];\n                }\n                if (a.length == 2) {\n                        var b = a[1];\n                        a = a[0];\n                        return a.length <= b.length ? a : b;\n                }\n                return best_of([ a[0], best_of(a.slice(1)) ]);\n        };\n\n        function needs_parens(expr) {\n                if (expr[0] == \"function\") {\n                        // dot/call on a literal function requires the\n                        // function literal itself to be parenthesized\n                        // only if it's the first \"thing\" in a\n                        // statement.  This means that the parent is\n                        // \"stat\", but it could also be a \"seq\" and\n                        // we're the first in this \"seq\" and the\n                        // parent is \"stat\", and so on.  Messy stuff,\n                        // but it worths the trouble.\n                        var a = slice($stack), self = a.pop(), p = a.pop();\n                        while (p) {\n                                if (p[0] == \"stat\") return true;\n                                if ((p[0] == \"seq\" && p[1] === self) ||\n                                    (p[0] == \"call\" && p[1] === self) ||\n                                    (p[0] == \"binary\" && p[2] === self)) {\n                                        self = p;\n                                        p = a.pop();\n                                } else {\n                                        return false;\n                                }\n                        }\n                }\n                return !HOP(DOT_CALL_NO_PARENS, expr[0]);\n        };\n\n        function make_num(num) {\n                var str = num.toString(10), a = [ str.replace(/^0\\./, \".\") ], m;\n                if (Math.floor(num) === num) {\n                        a.push(\"0x\" + num.toString(16).toLowerCase(), // probably pointless\n                               \"0\" + num.toString(8)); // same.\n                        if ((m = /^(.*?)(0+)$/.exec(num))) {\n                                a.push(m[1] + \"e\" + m[2].length);\n                        }\n                } else if ((m = /^0?\\.(0+)(.*)$/.exec(num))) {\n                        a.push(m[2] + \"e-\" + (m[1].length + m[2].length),\n                               str.substr(str.indexOf(\".\")));\n                }\n                return best_of(a);\n        };\n\n        var generators = {\n                \"string\": encode_string,\n                \"num\": make_num,\n                \"name\": make_name,\n                \"toplevel\": function(statements) {\n                        return make_block_statements(statements)\n                                .join(newline + newline);\n                },\n                \"block\": make_block,\n                \"var\": function(defs) {\n                        return \"var \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n                },\n                \"const\": function(defs) {\n                        return \"const \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n                },\n                \"try\": function(tr, ca, fi) {\n                        var out = [ \"try\", make_block(tr) ];\n                        if (ca) out.push(\"catch\", \"(\" + ca[0] + \")\", make_block(ca[1]));\n                        if (fi) out.push(\"finally\", make_block(fi));\n                        return add_spaces(out);\n                },\n                \"throw\": function(expr) {\n                        return add_spaces([ \"throw\", make(expr) ]) + \";\";\n                },\n                \"new\": function(ctor, args) {\n                        args = args.length > 0 ? \"(\" + add_commas(MAP(args, make)) + \")\" : \"\";\n                        return add_spaces([ \"new\", parenthesize(ctor, \"seq\", \"binary\", \"conditional\", \"assign\", function(expr){\n                                var w = ast_walker(), has_call = {};\n                                try {\n                                        w.with_walkers({\n                                                \"call\": function() { throw has_call },\n                                                \"function\": function() { return this }\n                                        }, function(){\n                                                w.walk(expr);\n                                        });\n                                } catch(ex) {\n                                        if (ex === has_call)\n                                                return true;\n                                        throw ex;\n                                }\n                        }) + args ]);\n                },\n                \"switch\": function(expr, body) {\n                        return add_spaces([ \"switch\", \"(\" + make(expr) + \")\", make_switch_block(body) ]);\n                },\n                \"break\": function(label) {\n                        var out = \"break\";\n                        if (label != null)\n                                out += \" \" + make_name(label);\n                        return out + \";\";\n                },\n                \"continue\": function(label) {\n                        var out = \"continue\";\n                        if (label != null)\n                                out += \" \" + make_name(label);\n                        return out + \";\";\n                },\n                \"conditional\": function(co, th, el) {\n                        return add_spaces([ parenthesize(co, \"assign\", \"seq\", \"conditional\"), \"?\",\n                                            parenthesize(th, \"seq\"), \":\",\n                                            parenthesize(el, \"seq\") ]);\n                },\n                \"assign\": function(op, lvalue, rvalue) {\n                        if (op && op !== true) op += \"=\";\n                        else op = \"=\";\n                        return add_spaces([ make(lvalue), op, parenthesize(rvalue, \"seq\") ]);\n                },\n                \"dot\": function(expr) {\n                        var out = make(expr), i = 1;\n                        if (expr[0] == \"num\")\n                                out += \".\";\n                        else if (needs_parens(expr))\n                                out = \"(\" + out + \")\";\n                        while (i < arguments.length)\n                                out += \".\" + make_name(arguments[i++]);\n                        return out;\n                },\n                \"call\": function(func, args) {\n                        var f = make(func);\n                        if (needs_parens(func))\n                                f = \"(\" + f + \")\";\n                        return f + \"(\" + add_commas(MAP(args, function(expr){\n                                return parenthesize(expr, \"seq\");\n                        })) + \")\";\n                },\n                \"function\": make_function,\n                \"defun\": make_function,\n                \"if\": function(co, th, el) {\n                        var out = [ \"if\", \"(\" + make(co) + \")\", el ? make_then(th) : make(th) ];\n                        if (el) {\n                                out.push(\"else\", make(el));\n                        }\n                        return add_spaces(out);\n                },\n                \"for\": function(init, cond, step, block) {\n                        var out = [ \"for\" ];\n                        init = (init != null ? make(init) : \"\").replace(/;*\\s*$/, \";\" + space);\n                        cond = (cond != null ? make(cond) : \"\").replace(/;*\\s*$/, \";\" + space);\n                        step = (step != null ? make(step) : \"\").replace(/;*\\s*$/, \"\");\n                        var args = init + cond + step;\n                        if (args == \"; ; \") args = \";;\";\n                        out.push(\"(\" + args + \")\", make(block));\n                        return add_spaces(out);\n                },\n                \"for-in\": function(vvar, key, hash, block) {\n                        return add_spaces([ \"for\", \"(\" +\n                                            (vvar ? make(vvar).replace(/;+$/, \"\") : make(key)),\n                                            \"in\",\n                                            make(hash) + \")\", make(block) ]);\n                },\n                \"while\": function(condition, block) {\n                        return add_spaces([ \"while\", \"(\" + make(condition) + \")\", make(block) ]);\n                },\n                \"do\": function(condition, block) {\n                        return add_spaces([ \"do\", make(block), \"while\", \"(\" + make(condition) + \")\" ]) + \";\";\n                },\n                \"return\": function(expr) {\n                        var out = [ \"return\" ];\n                        if (expr != null) out.push(make(expr));\n                        return add_spaces(out) + \";\";\n                },\n                \"binary\": function(operator, lvalue, rvalue) {\n                        var left = make(lvalue), right = make(rvalue);\n                        // XXX: I'm pretty sure other cases will bite here.\n                        //      we need to be smarter.\n                        //      adding parens all the time is the safest bet.\n                        if (member(lvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n                            lvalue[0] == \"binary\" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]]) {\n                                left = \"(\" + left + \")\";\n                        }\n                        if (member(rvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n                            rvalue[0] == \"binary\" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&\n                            !(rvalue[1] == operator && member(operator, [ \"&&\", \"||\", \"*\" ]))) {\n                                right = \"(\" + right + \")\";\n                        }\n                        return add_spaces([ left, operator, right ]);\n                },\n                \"unary-prefix\": function(operator, expr) {\n                        var val = make(expr);\n                        if (!(expr[0] == \"num\" || (expr[0] == \"unary-prefix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n                                val = \"(\" + val + \")\";\n                        return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? \" \" : \"\") + val;\n                },\n                \"unary-postfix\": function(operator, expr) {\n                        var val = make(expr);\n                        if (!(expr[0] == \"num\" || (expr[0] == \"unary-postfix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n                                val = \"(\" + val + \")\";\n                        return val + operator;\n                },\n                \"sub\": function(expr, subscript) {\n                        var hash = make(expr);\n                        if (needs_parens(expr))\n                                hash = \"(\" + hash + \")\";\n                        return hash + \"[\" + make(subscript) + \"]\";\n                },\n                \"object\": function(props) {\n                        if (props.length == 0)\n                                return \"{}\";\n                        return \"{\" + newline + with_indent(function(){\n                                return MAP(props, function(p){\n                                        if (p.length == 3) {\n                                                // getter/setter.  The name is in p[0], the arg.list in p[1][2], the\n                                                // body in p[1][3] and type (\"get\" / \"set\") in p[2].\n                                                return indent(make_function(p[0], p[1][2], p[1][3], p[2]));\n                                        }\n                                        var key = p[0], val = make(p[1]);\n                                        if (options.quote_keys) {\n                                                key = encode_string(key);\n                                        } else if ((typeof key == \"number\" || !beautify && +key + \"\" == key)\n                                                   && parseFloat(key) >= 0) {\n                                                key = make_num(+key);\n                                        } else if (!is_identifier(key)) {\n                                                key = encode_string(key);\n                                        }\n                                        return indent(add_spaces(beautify && options.space_colon\n                                                                 ? [ key, \":\", val ]\n                                                                 : [ key + \":\", val ]));\n                                }).join(\",\" + newline);\n                        }) + newline + indent(\"}\");\n                },\n                \"regexp\": function(rx, mods) {\n                        return \"/\" + rx + \"/\" + mods;\n                },\n                \"array\": function(elements) {\n                        if (elements.length == 0) return \"[]\";\n                        return add_spaces([ \"[\", add_commas(MAP(elements, function(el){\n                                if (!beautify && el[0] == \"atom\" && el[1] == \"undefined\") return \"\";\n                                return parenthesize(el, \"seq\");\n                        })), \"]\" ]);\n                },\n                \"stat\": function(stmt) {\n                        return make(stmt).replace(/;*\\s*$/, \";\");\n                },\n                \"seq\": function() {\n                        return add_commas(MAP(slice(arguments), make));\n                },\n                \"label\": function(name, block) {\n                        return add_spaces([ make_name(name), \":\", make(block) ]);\n                },\n                \"with\": function(expr, block) {\n                        return add_spaces([ \"with\", \"(\" + make(expr) + \")\", make(block) ]);\n                },\n                \"atom\": function(name) {\n                        return make_name(name);\n                }\n        };\n\n        // The squeezer replaces \"block\"-s that contain only a single\n        // statement with the statement itself; technically, the AST\n        // is correct, but this can create problems when we output an\n        // IF having an ELSE clause where the THEN clause ends in an\n        // IF *without* an ELSE block (then the outer ELSE would refer\n        // to the inner IF).  This function checks for this case and\n        // adds the block brackets if needed.\n        function make_then(th) {\n                if (th[0] == \"do\") {\n                        // https://github.com/mishoo/UglifyJS/issues/#issue/57\n                        // IE croaks with \"syntax error\" on code like this:\n                        //     if (foo) do ... while(cond); else ...\n                        // we need block brackets around do/while\n                        return make([ \"block\", [ th ]]);\n                }\n                var b = th;\n                while (true) {\n                        var type = b[0];\n                        if (type == \"if\") {\n                                if (!b[3])\n                                        // no else, we must add the block\n                                        return make([ \"block\", [ th ]]);\n                                b = b[3];\n                        }\n                        else if (type == \"while\" || type == \"do\") b = b[2];\n                        else if (type == \"for\" || type == \"for-in\") b = b[4];\n                        else break;\n                }\n                return make(th);\n        };\n\n        function make_function(name, args, body, keyword) {\n                var out = keyword || \"function\";\n                if (name) {\n                        out += \" \" + make_name(name);\n                }\n                out += \"(\" + add_commas(MAP(args, make_name)) + \")\";\n                return add_spaces([ out, make_block(body) ]);\n        };\n\n        function make_block_statements(statements) {\n                for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {\n                        var stat = statements[i];\n                        var code = make(stat);\n                        if (code != \";\") {\n                                if (!beautify && i == last) {\n                                        if ((stat[0] == \"while\" && empty(stat[2])) ||\n                                            (member(stat[0], [ \"for\", \"for-in\"] ) && empty(stat[4])) ||\n                                            (stat[0] == \"if\" && empty(stat[2]) && !stat[3]) ||\n                                            (stat[0] == \"if\" && stat[3] && empty(stat[3]))) {\n                                                code = code.replace(/;*\\s*$/, \";\");\n                                        } else {\n                                                code = code.replace(/;+\\s*$/, \"\");\n                                        }\n                                }\n                                a.push(code);\n                        }\n                }\n                return MAP(a, indent);\n        };\n\n        function make_switch_block(body) {\n                var n = body.length;\n                if (n == 0) return \"{}\";\n                return \"{\" + newline + MAP(body, function(branch, i){\n                        var has_body = branch[1].length > 0, code = with_indent(function(){\n                                return indent(branch[0]\n                                              ? add_spaces([ \"case\", make(branch[0]) + \":\" ])\n                                              : \"default:\");\n                        }, 0.5) + (has_body ? newline + with_indent(function(){\n                                return make_block_statements(branch[1]).join(newline);\n                        }) : \"\");\n                        if (!beautify && has_body && i < n - 1)\n                                code += \";\";\n                        return code;\n                }).join(newline) + newline + indent(\"}\");\n        };\n\n        function make_block(statements) {\n                if (!statements) return \";\";\n                if (statements.length == 0) return \"{}\";\n                return \"{\" + newline + with_indent(function(){\n                        return make_block_statements(statements).join(newline);\n                }) + newline + indent(\"}\");\n        };\n\n        function make_1vardef(def) {\n                var name = def[0], val = def[1];\n                if (val != null)\n                        name = add_spaces([ make_name(name), \"=\", make(val) ]);\n                return name;\n        };\n\n        var $stack = [];\n\n        function make(node) {\n                var type = node[0];\n                var gen = generators[type];\n                if (!gen)\n                        throw new Error(\"Can't find generator for \\\"\" + type + \"\\\"\");\n                $stack.push(node);\n                var ret = gen.apply(type, node.slice(1));\n                $stack.pop();\n                return ret;\n        };\n\n        return make(ast);\n};\n\nfunction split_lines(code, max_line_length) {\n        var splits = [ 0 ];\n        jsp.parse(function(){\n                var next_token = jsp.tokenizer(code);\n                var last_split = 0;\n                var prev_token;\n                function current_length(tok) {\n                        return tok.pos - last_split;\n                };\n                function split_here(tok) {\n                        last_split = tok.pos;\n                        splits.push(last_split);\n                };\n                function custom(){\n                        var tok = next_token.apply(this, arguments);\n                        out: {\n                                if (prev_token) {\n                                        if (prev_token.type == \"keyword\") break out;\n                                }\n                                if (current_length(tok) > max_line_length) {\n                                        switch (tok.type) {\n                                            case \"keyword\":\n                                            case \"atom\":\n                                            case \"name\":\n                                            case \"punc\":\n                                                split_here(tok);\n                                                break out;\n                                        }\n                                }\n                        }\n                        prev_token = tok;\n                        return tok;\n                };\n                custom.context = function() {\n                        return next_token.context.apply(this, arguments);\n                };\n                return custom;\n        }());\n        return splits.map(function(pos, i){\n                return code.substring(pos, splits[i + 1] || code.length);\n        }).join(\"\\n\");\n};\n\n/* -----[ Utilities ]----- */\n\nfunction repeat_string(str, i) {\n        if (i <= 0) return \"\";\n        if (i == 1) return str;\n        var d = repeat_string(str, i >> 1);\n        d += d;\n        if (i & 1) d += str;\n        return d;\n};\n\nfunction defaults(args, defs) {\n        var ret = {};\n        if (args === true)\n                args = {};\n        for (var i in defs) if (HOP(defs, i)) {\n                ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];\n        }\n        return ret;\n};\n\nfunction is_identifier(name) {\n        return /^[a-z_$][a-z0-9_$]*$/i.test(name)\n                && name != \"this\"\n                && !HOP(jsp.KEYWORDS_ATOM, name)\n                && !HOP(jsp.RESERVED_WORDS, name)\n                && !HOP(jsp.KEYWORDS, name);\n};\n\nfunction HOP(obj, prop) {\n        return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\n// some utilities\n\nvar MAP;\n\n(function(){\n        MAP = function(a, f, o) {\n                var ret = [];\n                for (var i = 0; i < a.length; ++i) {\n                        var val = f.call(o, a[i], i);\n                        if (val instanceof AtTop) ret.unshift(val.v);\n                        else ret.push(val);\n                }\n                return ret;\n        };\n        MAP.at_top = function(val) { return new AtTop(val) };\n        function AtTop(val) { this.v = val };\n})();\n\n/* -----[ Exports ]----- */\n\nexports.ast_walker = ast_walker;\nexports.ast_mangle = ast_mangle;\nexports.ast_squeeze = ast_squeeze;\nexports.gen_code = gen_code;\nexports.ast_add_scope = ast_add_scope;\nexports.ast_squeeze_more = require(\"./squeeze-more\").ast_squeeze_more;\nexports.set_logger = function(logger) { warn = logger };\nexports.make_string = make_string;\nexports.split_lines = split_lines;"
  },
  {
    "path": "build/lib/squeeze-more.js",
    "content": "var jsp = require(\"./parse-js\"),\n    pro = require(\"./process\"),\n    slice = jsp.slice,\n    member = jsp.member,\n    PRECEDENCE = jsp.PRECEDENCE,\n    OPERATORS = jsp.OPERATORS;\n\nfunction ast_squeeze_more(ast) {\n        var w = pro.ast_walker(), walk = w.walk;\n        return w.with_walkers({\n                \"call\": function(expr, args) {\n                        if (expr[0] == \"dot\" && expr[2] == \"toString\" && args.length == 0) {\n                                // foo.toString()  ==>  foo+\"\"\n                                return [ \"binary\", \"+\", expr[1], [ \"string\", \"\" ]];\n                        }\n                }\n        }, function() {\n                return walk(ast);\n        });\n};\n\nexports.ast_squeeze_more = ast_squeeze_more;\n"
  },
  {
    "path": "build/three.proton.js",
    "content": "/*!\n * three.proton v0.2.0\n * https://github.com/drawcall/three.proton\n *\n * Copyright 2011-2020, ajiemath\n * Licensed under the MIT license\n * http://www.opensource.org/licenses/mit-license\n *\n */\n(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('three')) :\n  typeof define === 'function' && define.amd ? define(['three'], factory) :\n  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Proton = factory(global.THREE));\n}(this, function (THREE) { \n\n\n    //the max particle number in pool\n    Proton.POOL_MAX = 500;\n    Proton.TIME_STEP = 60;\n    Proton.PI = 3.142;\n    Proton.DR = Proton.PI / 180;\n\n    //1:100\n    Proton.MEASURE = 100;\n    Proton.EULER = 'euler';\n    Proton.RK2 = 'runge-kutta2';\n    Proton.RK4 = 'runge-kutta4';\n    Proton.VERLET = 'verlet';\n\n    Proton.PARTICLE_CREATED = 'partilcleCreated';\n    Proton.PARTICLE_UPDATE = 'partilcleUpdate';\n    Proton.PARTICLE_SLEEP = 'particleSleep';\n    Proton.PARTICLE_DEAD = 'partilcleDead';\n    Proton.PROTON_UPDATE = 'protonUpdate';\n    Proton.PROTON_UPDATE_AFTER = 'protonUpdateAfter';\n    Proton.EMITTER_ADDED = 'emitterAdded';\n    Proton.EMITTER_REMOVED = 'emitterRemoved';\n\n    Proton.bindEmtterEvent = false;\n\n    /**\n     * @name Proton is a particle engine for three.js\n     *\n     * @class Proton\n     * @param {number} preParticles input any number\n     * @param {number} integrationType input any number\n     * @example var proton = new Proton(200);\n     */\n\n    function Proton(preParticles, integrationType) {\n        this.preParticles = Proton.Util.initValue(preParticles, Proton.POOL_MAX);\n        this.integrationType = Proton.Util.initValue(integrationType, Proton.EULER);\n\n        this.emitters = [];\n        this.renderers = [];\n\n        this.pool = new Proton.Pool();\n        Proton.integrator = new Proton.Integration(this.integrationType);\n    }\n\n\n    Proton.prototype = {\n        /**\n         * @name add a type of Renderer\n         *\n         * @method addRender\n         * @param {Renderer} render\n         */\n        addRender: function(renderer) {\n            this.renderers.push(renderer);\n            renderer.init(this);\n        },\n\n        /**\n         * @name add a type of Renderer\n         *\n         * @method addRender\n         * @param {Renderer} render\n         */\n        removeRender: function(renderer) {\n            this.renderers.splice(this.renderers.indexOf(renderer), 1);\n            renderer.remove(this);\n        },\n\n        /**\n         * add the Emitter\n         *\n         * @method addEmitter\n         * @param {Emitter} emitter\n         */\n        addEmitter: function(emitter) {\n            this.emitters.push(emitter);\n            emitter.parent = this;\n            this.dispatchEvent(\"EMITTER_ADDED\", emitter);\n        },\n\n        removeEmitter: function(emitter) {\n            if (emitter.parent != this) return;\n\n            this.emitters.splice(this.emitters.indexOf(emitter), 1);\n            emitter.parent = null;\n            this.dispatchEvent(\"EMITTER_REMOVED\", emitter);\n        },\n\n        update: function($delta) {\n            this.dispatchEvent(\"PROTON_UPDATE\", this);\n\n            var delta = $delta || 0.0167;\n            if (delta > 0) {\n                var i = this.emitters.length;\n                while (i--) this.emitters[i].update(delta);\n            }\n\n            this.dispatchEvent(\"PROTON_UPDATE_AFTER\", this);\n        },\n\n        /**\n         * getCount\n         * @name get the count of particle\n         * @return (number) particles count\n         */\n        getCount: function() {\n            var total = 0;\n            var i, length = this.emitters.length;\n            for (i = 0; i < length; i++) total += this.emitters[i].particles.length;\n            return total;\n        },\n\n        /**\n         * destroy\n         * @name destroy the proton\n         */\n        destroy: function() {\n            var i = 0,\n                length = this.emitters.length;\n\n            for (i; i < length; i++) {\n                this.emitters[i].destroy();\n                delete this.emitters[i];\n            }\n\n            this.emitters.length = 0;\n            this.pool.destroy();\n        }\n    };\n\n    \n\n\n/*\n * EventDispatcher\n * Visit http://createjs.com/ for documentation, updates and examples.\n *\n **/\n\n\n    function EventDispatcher() {\n        this.initialize();\n    };\n\n    EventDispatcher.initialize = function(target) {\n        target.addEventListener = p.addEventListener;\n        target.removeEventListener = p.removeEventListener;\n        target.removeAllEventListeners = p.removeAllEventListeners;\n        target.hasEventListener = p.hasEventListener;\n        target.dispatchEvent = p.dispatchEvent;\n    };\n\n    var p = EventDispatcher.prototype;\n\n    p._listeners = null;\n\n    p.initialize = function() {};\n    p.addEventListener = function(type, listener) {\n        if (!this._listeners) {\n            this._listeners = {};\n        } else {\n            this.removeEventListener(type, listener);\n        }\n\n        if (!this._listeners[type]) this._listeners[type] = []\n        this._listeners[type].push(listener);\n\n        return listener;\n    };\n\n    p.removeEventListener = function(type, listener) {\n        if (!this._listeners) return;\n        if (!this._listeners[type]) return;\n\n        var arr = this._listeners[type];\n        for (var i = 0, l = arr.length; i < l; i++) {\n            if (arr[i] == listener) {\n                if (l == 1) {\n                    delete(this._listeners[type]);\n                }\n                // allows for faster checks.\n                else {\n                    arr.splice(i, 1);\n                }\n                break;\n            }\n        }\n    };\n\n    p.removeAllEventListeners = function(type) {\n        if (!type)\n            this._listeners = null;\n        else if (this._listeners)\n            delete(this._listeners[type]);\n    };\n\n    p.dispatchEvent = function(eventName, eventTarget) {\n        var ret = false,\n            listeners = this._listeners;\n\n        if (eventName && listeners) {\n            var arr = listeners[eventName];\n            if (!arr) return ret;\n\n            arr = arr.slice();\n            // to avoid issues with items being removed or added during the dispatch\n\n            var handler, i = arr.length;\n            while (i--) {\n                var handler = arr[i];\n                ret = ret || handler(eventTarget);\n            }\n            \n        }\n\n        return !!ret;\n    };\n\n    p.hasEventListener = function(type) {\n        var listeners = this._listeners;\n        return !!(listeners && listeners[type]);\n    };\n\n    EventDispatcher.initialize(Proton.prototype);\n    Proton.EventDispatcher = EventDispatcher;\n\n\n\n    var Util = Util || {\n        initValue: function(value, defaults) {\n            var value = (value != null && value != undefined) ? value : defaults;\n            return value;\n        },\n\n        isArray: function(value) {\n            return Object.prototype.toString.call(value) === '[object Array]';\n        },\n\n        destroyArray: function(array) {\n            array.length = 0;\n        },\n\n        destroyObject: function(obj) {\n            for (var o in obj) delete obj[o];\n        },\n\n        isUndefined: function() {\n            for (var id in arguments) {\n                var arg = arguments[id];\n                if (arg !== undefined)\n                    return false;\n            }\n\n            return true;\n        },\n\n        setVectorByObj: function(target, pOBJ) {\n            if (pOBJ[\"x\"] !== undefined) target.p.x = pOBJ[\"x\"];\n            if (pOBJ[\"y\"] !== undefined) target.p.y = pOBJ[\"y\"];\n            if (pOBJ[\"z\"] !== undefined) target.p.z = pOBJ[\"z\"];\n\n            if (pOBJ[\"vx\"] !== undefined) target.v.x = pOBJ[\"vx\"];\n            if (pOBJ[\"vy\"] !== undefined) target.v.y = pOBJ[\"vy\"];\n            if (pOBJ[\"vz\"] !== undefined) target.v.z = pOBJ[\"vz\"];\n\n            if (pOBJ[\"ax\"] !== undefined) target.a.x = pOBJ[\"ax\"];\n            if (pOBJ[\"ay\"] !== undefined) target.a.y = pOBJ[\"ay\"];\n            if (pOBJ[\"az\"] !== undefined) target.a.z = pOBJ[\"az\"];\n\n            if (pOBJ[\"p\"] !== undefined) target.p.copy(pOBJ[\"p\"]);\n            if (pOBJ[\"v\"] !== undefined) target.v.copy(pOBJ[\"v\"]);\n            if (pOBJ[\"a\"] !== undefined) target.a.copy(pOBJ[\"a\"]);\n\n            if (pOBJ[\"position\"] !== undefined) target.p.copy(pOBJ[\"position\"]);\n            if (pOBJ[\"velocity\"] !== undefined) target.v.copy(pOBJ[\"velocity\"]);\n            if (pOBJ[\"accelerate\"] !== undefined) target.a.copy(pOBJ[\"accelerate\"]);\n        },\n\n        //set prototype\n        setPrototypeByObj: function(target, proObj, filters) {\n            for (var key in proObj) {\n                if (target.hasOwnProperty(key)) {\n                    if (filters) {\n                        if (filters.indexOf(key) < 0) target[key] = Util._getValue(proObj[key]);\n                    } else {\n                        target[key] = Util._getValue(proObj[key]);\n                    }\n                }\n            }\n\n            return target;\n        },\n\n        _getValue: function(pan) {\n            if (pan instanceof Span)\n                return pan.getValue();\n            else\n                return pan;\n        },\n\n        inherits: function(subClass, superClass) {\n            subClass._super_ = superClass;\n            if (Object['create']) {\n                subClass.prototype = Object.create(superClass.prototype, {\n                    constructor: { value: subClass }\n                });\n            } else {\n                var F = function() {};\n                F.prototype = superClass.prototype;\n                subClass.prototype = new F();\n                subClass.prototype.constructor = subClass;\n            }\n        }\n    };\n\n    Proton.Util = Util;\n\n\n\n    var ColorUtil = ColorUtil || {\n        getRGB: function(color) {\n            var rgb = {};\n            if (typeof color === 'number') {\n                hex = Math.floor(color);\n                rgb.r = (color >> 16 & 255) / 255;\n                rgb.g = (color >> 8 & 255) / 255;\n                rgb.b = (color & 255) / 255;\n            } else if (typeof color === 'string') {\n                var m;\n                if (m = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec(color)) {\n                    rgb.r = Math.min(255, parseInt(m[1], 10)) / 255;\n                    rgb.g = Math.min(255, parseInt(m[2], 10)) / 255;\n                    rgb.b = Math.min(255, parseInt(m[3], 10)) / 255;\n                } else if (m = /^\\#([A-Fa-f0-9]+)$/.exec(color)) {\n                    var hex = m[1];\n                    rgb.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255;\n                    rgb.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255;\n                    rgb.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255;\n                }\n            } else if (color instanceof THREE.Color) {\n                rgb.r = color.r;\n                rgb.g = color.g;\n                rgb.b = color.b;\n            }\n\n            return rgb;\n        }\n    };\n\n\n    Proton.ColorUtil = ColorUtil;\n\n\n\n    var THREEUtil = {\n        toScreenPos: function() {\n            var vector = new THREE.Vector3();\n\n            return function(pos, camera, canvas) {\n                vector.copy(pos);\n                // map to normalized device coordinate (NDC) space\n                vector.project(camera);\n                // map to 2D screen space\n                vector.x = Math.round((vector.x + 1) * canvas.width / 2);\n                vector.y = Math.round((-vector.y + 1) * canvas.height / 2);\n                vector.z = 0;\n\n                return vector;\n            }\n        }(),\n\n        toSpacePos: function() {\n            var vector = new THREE.Vector3(),\n                dir = new THREE.Vector3(),\n                distance;\n\n            return function(pos, camera, canvas) {\n                vector.set((pos.x / canvas.width) * 2 - 1, -(pos.y / canvas.height) * 2 + 1, 0.5);\n                vector.unproject(camera);\n\n                dir.copy(vector.sub(camera.position).normalize());\n                distance = -camera.position.z / dir.z;\n                vector.copy(camera.position);\n                vector.add(dir.multiplyScalar(distance));\n\n                return vector;\n            }\n        }(),\n\n        getTexture: function() {\n            var store = {};\n\n            return function(img) {\n                if (img instanceof THREE.Texture) {\n                    return img;\n                } else if (typeof img == \"string\") {\n                    var id = Proton.PUID.hash(img);\n                    if (!store[id]) store[id] = new THREE.Texture(img);;\n                    return store[id];\n                } else if (img instanceof Image) {\n                    var id = Proton.PUID.hash(img.src);\n                    if (!store[id]) store[id] = new THREE.Texture(img);;\n                    return store[id];\n                }\n            }\n        }()\n    };\n\n    Proton.THREEUtil = THREEUtil;\n\n\n\n    var PUID = PUID || {\n        _id: 0,\n        _uids: {},\n        id: function(obj) {\n            for (var id in this._uids) {\n                if (this._uids[id] == obj) return id;\n            }\n\n            var nid = \"PUID_\" + (this._id++);\n            this._uids[nid] = obj;\n            return nid;\n        },\n\n        hash: function(str) {\n            return;\n        }\n    }\n\n    Proton.PUID = PUID;\n\n\n\n\n    Particle.ID = 0;\n\n    /**\n     * the Particle class\n     * @param {Number} pObj - the parameters of particle config;\n     * @example \n     * var p = new Proton.Particle({life:3,dead:false});\n     * or\n     * var p = new Proton.Particle({mass:1,radius:100});\n     * @constructor\n     */\n    function Particle(pOBJ) {\n        /**\n         * @property {Number}  id               - The particle's id\n         */\n        this.id = 'particle_' + Particle.ID++;\n        this.name = 'Particle';\n        this.reset(\"init\");\n        Proton.Util.setPrototypeByObj(this, pOBJ);\n    }\n\n    Particle.prototype = {\n        getDirection: function() {\n            return Math.atan2(this.v.x, -this.v.y) * (180 / Proton.PI);\n        },\n\n        /**\n         * @property {Number}  life               - The particle's life\n         * @property {Number}  age               - The particle's age\n         * @property {Number}  energy               - The particle's energy loss\n         * @property {Boolean}  dead               - The particle is dead?\n         * @property {Boolean}  sleep               - The particle is sleep?\n         * @property {Object}  target               - The particle's target\n         * @property {Object}  body               - The particle's body\n         * @property {Number}  mass               - The particle's mass\n         * @property {Number}  radius               - The particle's radius\n         * @property {Number}  alpha               - The particle's alpha\n         * @property {Number}  scale               - The particle's scale\n         * @property {Number}  rotation               - The particle's rotation\n         * @property {String|Number}  color               - The particle's color\n         * @property {Function}  easing               - The particle's easing\n         * @property {Proton.Vector3D}  p               - The particle's position\n         * @property {Proton.Vector3D}  v               - The particle's velocity\n         * @property {Proton.Vector3D}  a               - The particle's acceleration\n         * @property {Array}  behaviours               - The particle's behaviours array\n         * @property {Object}  transform               - The particle's transform collection\n         */\n        reset: function(init) {\n            this.life = Infinity;\n            this.age = 0;\n            //energy loss\n            this.energy = 1;\n            this.dead = false;\n            this.sleep = false;\n            this.body = null;\n            this.parent = null;\n            this.mass = 1;\n            this.radius = 10;\n\n            this.alpha = 1;\n            this.scale = 1;\n\n            this.useColor = false;\n            this.useAlpha = false;\n\n            this.easing = Proton.ease.setEasingByName(Proton.ease.easeLinear);\n\n            if (init) {\n                this.p = new Proton.Vector3D();\n                this.v = new Proton.Vector3D();\n                this.a = new Proton.Vector3D();\n                this.old = {};\n                this.old.p = this.p.clone();\n                this.old.v = this.v.clone();\n                this.old.a = this.a.clone();\n\n                this.behaviours = [];\n                this.transform = {};\n                this.color = { r: 0, g: 0, b: 0 };\n                this.rotation = new Proton.Vector3D;\n            } else {\n                this.p.set(0, 0, 0);\n                this.v.set(0, 0, 0);\n                this.a.set(0, 0, 0);\n                this.old.p.set(0, 0, 0);\n                this.old.v.set(0, 0, 0);\n                this.old.a.set(0, 0, 0);\n\n                this.color.r = 0;\n                this.color.g = 0;\n                this.color.b = 0;\n\n                this.rotation.clear();\n\n                Proton.Util.destroyObject(this.transform);\n                this.removeAllBehaviours();\n            }\n\n            return this;\n        },\n\n        update: function(time, index) {\n            if (!this.sleep) {\n                this.age += time;\n\n                var i = this.behaviours.length;\n                while (i--) {\n                    this.behaviours[i] && this.behaviours[i].applyBehaviour(this, time, index)\n                }\n            } else {\n                //sleep\n            }\n\n            if (this.age >= this.life) {\n                this.destroy();\n            } else {\n                var scale = this.easing(this.age / this.life);\n                this.energy = Math.max(1 - scale, 0);\n            }\n\n        },\n\n        addBehaviour: function(behaviour) {\n            this.behaviours.push(behaviour);\n            behaviour.initialize(this);\n        },\n\n        addBehaviours: function(behaviours) {\n            var i = behaviours.length;\n            while (i--) {\n                this.addBehaviour(behaviours[i]);\n            }\n        },\n\n        removeBehaviour: function(behaviour) {\n            var index = this.behaviours.indexOf(behaviour);\n            if (index > -1) {\n                this.behaviours.splice(index, 1);\n            }\n        },\n\n        removeAllBehaviours: function() {\n            Proton.Util.destroyArray(this.behaviours);\n        },\n\n        /**\n         * Destory this particle\n         * @method destroy\n         */\n        destroy: function() {\n            this.removeAllBehaviours();\n            this.energy = 0;\n            this.dead = true;\n            this.parent = null;\n        }\n    };\n\n    Proton.Particle = Particle;\n\n\n\n\n    function Pool() {\n        this.cID = 0;\n        this.list = {};\n    }\n\n    Pool.prototype = {\n        create: function(obj) {\n            this.cID++;\n\n            if (typeof obj == \"function\")\n                return new obj;\n            else\n                return obj.clone();\n        },\n\n        getCount: function() {\n            var count = 0;\n            for (var id in this.list)\n                count += this.list[id].length;\n\n            return count++;;\n        },\n\n        get: function(obj) {\n            var p, puid = obj.__puid || Proton.PUID.id(obj);\n            if (this.list[puid] && this.list[puid].length > 0)\n                p = this.list[puid].pop();\n            else\n                p = this.create(obj);\n\n            p.__puid = obj.__puid || puid;\n            return p;\n        },\n\n        expire: function(obj) {\n            return this._getList(obj.__puid).push(obj);\n        },\n\n        destroy: function() {\n            for (var id in this.list) {\n                this.list[id].length = 0;\n                delete this.list[id];\n            }\n        },\n\n        _getList: function(uid) {\n            uid = uid || \"default\";\n            if (!this.list[uid]) this.list[uid] = [];\n            return this.list[uid];\n        }\n    }\n\n    Proton.Pool = Pool;\n\n\n\n\n    var MathUtils = {\n        randomAToB: function(a, b, INT) {\n            if (!INT)\n                return a + Math.random() * (b - a);\n            else\n                return ((Math.random() * (b - a)) >> 0) + a;\n        },\n        randomFloating: function(center, f, INT) {\n            return MathUtils.randomAToB(center - f, center + f, INT);\n        },\n\n        randomZone: function(display) {\n\n        },\n\n        degreeTransform: function(a) {\n            return a * Proton.PI / 180;\n        },\n\n        toColor16: function getRGB(num) {\n            return \"#\" + num.toString(16);\n        },\n\n        randomColor: function() {\n            return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6);\n        },\n\n        lerp: function(a, b, energy) {\n            return b + (a - b) * energy\n        },\n\n        getNormal: function(v, n) {\n            if (v.x == 0 && v.y == 0) {\n                if (v.z == 0)\n                    n.set(1, 0, 1);\n                else\n                    n.set(1, 1, -v.y / v.z);\n            } else {\n                if (v.x == 0)\n                    n.set(1, 0, 1);\n                else\n                    n.set(-v.y / v.x, 1, 1);\n            }\n\n            return n.normalize();\n        },\n\n        /** \n         * Rodrigues' Rotation Formula \n         * https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula\n         * v′ = vcos(θ) + k(k⋅v)(1−cos(θ)) + (k*v)sin(θ)\n         */\n        axisRotate: function(v0, v, k, tha) {\n            var cos = Math.cos(tha);\n            var sin = Math.sin(tha);\n            var p = k.dot(v) * (1 - cos);\n\n            v0.copy(k);\n            v0.cross(v).scalar(sin);\n            v0.addValue(v.x * cos, v.y * cos, v.z * cos);\n            v0.addValue(k.x * p, k.y * p, k.z * p);\n        }\n    }\n\n    Proton.MathUtils = MathUtils;\n\n\n//数值积分\n\n    var Integration = function(type) {\n        this.type = Proton.Util.initValue(type, Proton.EULER);\n    }\n\n    Integration.prototype = {\n        integrate: function(particles, time, damping) {\n            this.euler(particles, time, damping);\n        },\n\n        euler: function(particle, time, damping) {\n            if (!particle.sleep) {\n                particle.old.p.copy(particle.p);\n                particle.old.v.copy(particle.v);\n                particle.a.scalar(1 / particle.mass);\n                particle.v.add(particle.a.scalar(time));\n                particle.p.add(particle.old.v.scalar(time));\n                damping && particle.v.scalar(damping);\n                particle.a.clear();\n            }\n        }\n    }\n\n    Proton.Integration = Integration;\n\n\n//@author mrdoob / http://mrdoob.com/\n\n    var Vector3D = function(x, y, z) {\n        this.x = x || 0;\n        this.y = y || 0;\n        this.z = z || 0;\n    }\n\n    Vector3D.prototype = {\n        set: function(x, y, z) {\n            this.x = x;\n            this.y = y;\n            this.z = z;\n            return this;\n        },\n\n        setX: function(x) {\n            this.x = x;\n            return this;\n        },\n\n        setY: function(y) {\n            this.y = y;\n            return this;\n        },\n\n        setZ: function(z) {\n            this.z = z;\n            return this;\n        },\n\n        getGradient: function() {\n            if (this.x != 0)\n                return Math.atan2(this.y, this.x);\n            else if (this.y > 0)\n                return Proton.PI / 2;\n            else if (this.y < 0)\n                return -Proton.PI / 2;\n        },\n\n        copy: function(v) {\n            this.x = v.x;\n            this.y = v.y;\n            this.z = v.z;\n            return this;\n        },\n\n        add: function(v, w) {\n            if (w !== undefined) return this.addVectors(v, w);\n\n            this.x += v.x;\n            this.y += v.y;\n            this.z += v.z;\n\n            return this;\n\n        },\n\n        addValue: function(a, b, c) {\n            this.x += a;\n            this.y += b;\n            this.z += c;\n\n            return this;\n\n        },\n\n        addVectors: function(a, b) {\n            this.x = a.x + b.x;\n            this.y = a.y + b.y;\n            this.z = a.z + b.z;\n\n            return this;\n        },\n\n        addScalar: function(s) {\n            this.x += s;\n            this.y += s;\n            this.z += s;\n\n            return this;\n        },\n\n        sub: function(v, w) {\n            if (w !== undefined) return this.subVectors(v, w);\n\n            this.x -= v.x;\n            this.y -= v.y;\n            this.z -= v.z;\n\n            return this;\n        },\n\n        subVectors: function(a, b) {\n            this.x = a.x - b.x;\n            this.y = a.y - b.y;\n            this.z = a.z - b.z;\n            return this;\n        },\n\n        scalar: function(s) {\n            this.x *= s;\n            this.y *= s;\n            this.z *= s;\n\n            return this;\n        },\n\n        divideScalar: function(s) {\n            if (s !== 0) {\n                this.x /= s;\n                this.y /= s;\n                this.z /= s;\n            } else {\n                this.set(0, 0, 0);\n            }\n\n            return this;\n        },\n\n        negate: function() {\n            return this.scalar(-1);\n        },\n\n        dot: function(v) {\n            return this.x * v.x + this.y * v.y + this.z * v.z;\n        },\n\n        cross: function(v) {\n            var x = this.x,\n                y = this.y,\n                z = this.z;\n\n            this.x = y * v.z - z * v.y;\n            this.y = z * v.x - x * v.z;\n            this.z = x * v.y - y * v.x;\n\n            return this;\n        },\n\n        lengthSq: function() {\n            return this.x * this.x + this.y * this.y + this.z * this.z;\n        },\n\n        length: function() {\n            return Math.sqrt(this.lengthSq());\n        },\n\n        normalize: function() {\n            return this.divideScalar(this.length());\n        },\n\n        distanceTo: function(v) {\n            return Math.sqrt(this.distanceToSquared(v));\n        },\n\n        crossVectors: function(a, b) {\n\n            var ax = a.x,\n                ay = a.y,\n                az = a.z;\n            var bx = b.x,\n                by = b.y,\n                bz = b.z;\n\n            this.x = ay * bz - az * by;\n            this.y = az * bx - ax * bz;\n            this.z = ax * by - ay * bx;\n\n            return this;\n\n        },\n\n        // eulerFromDir: function() {\n        //     var quaternion, dir, up;\n\n        //     return function rotateFromDir(direction) {\n        //         if (quaternion === undefined) quaternion = new Proton.Quaternion();\n        //         if (dir === undefined) dir = new Proton.Vector3D;\n        //         if (up === undefined) up = new Proton.Vector3D(0, 0, 1);\n\n        //         //quaternion.setFromUnitVectors(up, dir.copy(direction).normalize());\n        //         console.log(quaternion.setFromUnitVectors(up, dir.copy(direction).normalize()));\n\n        //         this.applyQuaternion(quaternion.setFromUnitVectors(up, dir.copy(direction).normalize()));\n        //             console.log(this);\n        //         return this;\n        //     };\n        // }(),\n\n        eulerFromDir: function(dir) {\n            \n        },\n\n        applyEuler: function() {\n            var quaternion;\n\n            return function applyEuler(euler) {\n                if (quaternion === undefined) quaternion = new Proton.Quaternion();\n                this.applyQuaternion(quaternion.setFromEuler(euler));\n                return this;\n            };\n        }(),\n\n        applyAxisAngle: function() {\n            var quaternion;\n            return function applyAxisAngle(axis, angle) {\n                if (quaternion === undefined) quaternion = new Proton.Quaternion();\n                this.applyQuaternion(quaternion.setFromAxisAngle(axis, angle));\n                return this;\n            };\n        }(),\n\n        applyQuaternion: function(q) {\n            var x = this.x;\n            var y = this.y;\n            var z = this.z;\n\n            var qx = q.x;\n            var qy = q.y;\n            var qz = q.z;\n            var qw = q.w;\n\n            // calculate quat * vector\n\n            var ix = qw * x + qy * z - qz * y;\n            var iy = qw * y + qz * x - qx * z;\n            var iz = qw * z + qx * y - qy * x;\n            var iw = -qx * x - qy * y - qz * z;\n\n            // calculate result * inverse quat\n            this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;\n            this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;\n            this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;\n            return this;\n        },\n\n        distanceToSquared: function(v) {\n            var dx = this.x - v.x,\n                dy = this.y - v.y,\n                dz = this.z - v.z;\n\n            return dx * dx + dy * dy + dz * dz;\n        },\n\n        lerp: function(v, alpha) {\n            this.x += (v.x - this.x) * alpha;\n            this.y += (v.y - this.y) * alpha;\n            this.z += (v.z - this.z) * alpha;\n            return this;\n        },\n\n        equals: function(v) {\n            return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));\n        },\n\n        clear: function() {\n            this.x = 0.0;\n            this.y = 0.0;\n            this.z = 0.0;\n            return this;\n        },\n\n        clone: function() {\n            return new Proton.Vector3D(this.x, this.y, this.z);\n        },\n\n        toString: function() {\n            return \"x:\" + this.x + \"y:\" + this.y + \"z:\" + this.z;\n        }\n    };\n\n    Proton.Vector3D = Vector3D;\n\n\n\n    var Polar3D = function(radius, theta, phi) {\n        this.radius = radius || 1;\n        this.phi = phi || 0;\n        this.theta = theta || 0;\n    }\n\n    Polar3D.prototype = {\n        set: function(radius, theta, phi) {\n            this.radius = radius || 1;\n            this.phi = phi || 0;\n            this.theta = theta || 0;\n\n            return this;\n        },\n\n        setRadius: function(radius) {\n            this.radius = radius;\n            return this;\n        },\n\n        setPhi: function(phi) {\n            this.phi = phi;\n            return this;\n        },\n\n        setTheta: function(theta) {\n            this.theta = theta;\n            return this;\n        },\n\n        copy: function(p) {\n            this.radius = p.radius;\n            this.phi = p.phi;\n            this.theta = p.theta;\n            return this;\n        },\n\n        toVector3D: function() {\n            return new Proton.Vector3D(this.getX(), this.getY(), this.getZ());\n        },\n\n        getX: function() {\n            return this.radius * Math.sin(this.theta) * Math.cos(this.phi);\n        },\n\n        getY: function() {\n            return -this.radius * Math.sin(this.theta) * Math.sin(this.phi);\n        },\n\n        getZ: function() {\n            return this.radius * Math.cos(this.theta);\n        },\n\n        normalize: function() {\n            this.radius = 1;\n            return this;\n        },\n\n        equals: function(v) {\n            return ((v.radius === this.radius) && (v.phi === this.phi) && (v.theta === this.theta));\n        },\n\n        clear: function() {\n            this.radius = 0.0;\n            this.phi = 0.0;\n            this.theta = 0.0;\n            return this;\n        },\n\n        clone: function() {\n            return new Polar3D(this.radius, this.phi, this.theta);\n        }\n    };\n\n\n    Proton.Polar3D = Polar3D;\n\n\n\n    /**\n     * Span Class. Get a random Number from a to b. Or from c-a to c+b\n     * @param {Number|Array} a - min number\n     * @param {Number} b - max number\n     * @param {Number} center - the center's z value  \n     * @example \n     * var span = new Proton.Span(0,30);\n     * or\n     * var span = new Proton.Span([\"#fff\",\"#ff0\",\"#000\"]);\n     * or\n     * var span = new Proton.Span(5,1,\"center\");\n     * @extends {Zone}\n     * @constructor\n     */\n    function Span(a, b, center) {\n        this._isArray = false;\n\n        if (Proton.Util.isArray(a)) {\n            this._isArray = true;\n            this.a = a;\n        } else {\n            this.a = Proton.Util.initValue(a, 1);\n            this.b = Proton.Util.initValue(b, this.a);\n            this._center = Proton.Util.initValue(center, false);\n        }\n    }\n\n    /**\n     * Span.getValue function\n     * @name get a random Number from a to b. Or get a random Number from c-a to c+b\n     * @param {number} INT or int\n     * @return {number} a random Number\n     */\n    Span.prototype = {\n        getValue: function(INT) {\n            if (this._isArray) {\n                return this.a[(this.a.length * Math.random()) >> 0];\n            } else {\n                if (!this._center)\n                    return Proton.MathUtils.randomAToB(this.a, this.b, INT);\n                else\n                    return Proton.MathUtils.randomFloating(this.a, this.b, INT);\n            }\n        }\n    }\n\n    /**\n     * Proton.createSpan function\n     * @name get a instance of Span\n     * @param {number} a min number\n     * @param {number} b max number\n     * @param {number} c center number\n     * @return {number} return a instance of Span\n     */\n    Proton.createSpan = function(a, b, c) {\n        if (a instanceof Span) return a;\n\n        if (b === undefined) {\n            return new Span(a);\n        } else {\n            if (c === undefined)\n                return new Span(a, b);\n            else\n                return new Span(a, b, c);\n        }\n    }\n\n    Proton.Span = Span;\n\n\n\n    /**\n     * ArraySpan name get a random Color from a colors array\n     * @param {String|Array} colors - colors array\n     * @example \n     * var span = new Proton.ArraySpan([\"#fff\",\"#ff0\",\"#000\"]);\n     * or\n     * var span = new Proton.ArraySpan(\"#ff0\");\n     * @extends {Proton.Span}\n     * @constructor\n     */\n\n    function ArraySpan(colors) {\n        this._arr = Proton.Util.isArray(colors) ? colors : [colors];\n    }\n\n    Proton.Util.inherits(ArraySpan, Proton.Span);\n\n    /**\n     * getValue function\n     * @name get a random Color\n     * @return {string} a hex color\n     */\n    ArraySpan.prototype.getValue = function() {\n        var color = this._arr[(this._arr.length * Math.random()) >> 0];\n        \n        if (color == 'random' || color == 'Random')\n            return Proton.MathUtils.randomColor();\n        else\n            return color;\n    }\n\n    /**\n     * Proton.createArraySpan function\n     * @name get a instance of Span\n     * @param {number} a min number\n     * @param {number} b max number\n     * @param {number} c center number\n     * @return {number} return a instance of Span\n     */\n    Proton.createArraySpan = function(arr) {\n        if (!arr) return null;\n        if (arr instanceof Proton.ArraySpan)\n            return arr;\n        else \n            return new Proton.ArraySpan(arr);\n    }\n\n    Proton.ArraySpan = ArraySpan;\n\n\n\n\n\n    var Quaternion = function(x, y, z, w) {\n        this.x = x || 0;\n        this.y = y || 0;\n        this.z = z || 0;\n        this.w = (w !== undefined) ? w : 1;\n    };\n\n    Quaternion.prototype = {\n        set: function(x, y, z, w) {\n            this.x = x;\n            this.y = y;\n            this.z = z;\n            this.w = w;\n            return this;\n        },\n\n        clone: function() {\n            return new Proton.Quaternion(this.x, this.y, this.z, this.w);\n        },\n\n        copy: function(quaternion) {\n            this.x = quaternion.x;\n            this.y = quaternion.y;\n            this.z = quaternion.z;\n            this.w = quaternion.w;\n            return this;\n        },\n\n        setFromEuler: function(euler) {\n            // http://www.mathworks.com/matlabcentral/fileexchange/\n            //  20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\n            //  content/SpinCalc.m\n\n            var c1 = Math.cos(euler.x / 2);\n            var c2 = Math.cos(euler.y / 2);\n            var c3 = Math.cos(euler.z / 2);\n            var s1 = Math.sin(euler.x / 2);\n            var s2 = Math.sin(euler.y / 2);\n            var s3 = Math.sin(euler.z / 2);\n\n            this.x = s1 * c2 * c3 + c1 * s2 * s3;\n            this.y = c1 * s2 * c3 - s1 * c2 * s3;\n            this.z = c1 * c2 * s3 + s1 * s2 * c3;\n            this.w = c1 * c2 * c3 - s1 * s2 * s3;\n\n            return this;\n\n        },\n\n        setFromAxisAngle: function(axis, angle) {\n            // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\n            // assumes axis is normalized\n            var halfAngle = angle / 2,\n                s = Math.sin(halfAngle);\n            this.x = axis.x * s;\n            this.y = axis.y * s;\n            this.z = axis.z * s;\n            this.w = Math.cos(halfAngle);\n\n            return this;\n        },\n\n        // setFromUnitVectors: function() {\n        //     var v1, r;\n        //     var EPS = 0.000001;\n\n        //     return function(vFrom, vTo) {\n        //         if (v1 === undefined) v1 = new Proton.Vector3D();\n\n        //         r = vFrom.dot(vTo) + 1;\n        //         if (r < EPS) {\n        //             r = 0;\n        //             if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {\n        //                 v1.set(-vFrom.y, vFrom.x, 0);\n        //             } else {\n        //                 v1.set(0, -vFrom.z, vFrom.y);\n        //             }\n        //         } else {\n        //             v1.crossVectors(vFrom, vTo);\n        //         }\n\n        //         this.x = v1.x;\n        //         this.y = v1.y;\n        //         this.z = v1.z;\n        //         this.w = r;\n        //         return this.normalize();\n        //     };\n        // }(),\n\n        normalize: function() {\n\n            var l = this.length();\n\n            if (l === 0) {\n\n                this.x = 0;\n                this.y = 0;\n                this.z = 0;\n                this.w = 1;\n\n            } else {\n                l = 1 / l;\n                this.x *= l;\n                this.y *= l;\n                this.z *= l;\n                this.w *= l;\n\n            }\n            return this;\n        },\n\n        length: function() {\n\n            return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\n\n        },\n\n        dot: function(v) {\n            return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\n        }\n    };\n\n    Proton.Quaternion = Quaternion;\n\n\n\n    function Box(x, y, z, w, h, d) {\n        this.x = x;\n        this.y = y;\n        this.z = z;\n        this.width = w;\n        this.height = h;\n        this.depth = d;\n        this.bottom = this.y + this.height;\n        this.right = this.x + this.width;\n        this.right = this.x + this.width;\n    }\n\n\n    Box.prototype = {\n        contains: function(x, y, z) {\n            if (\n                x <= this.right &&\n                x >= this.x &&\n                y <= this.bottom &&\n                y >= this.y &&\n                z <= this.depth &&\n                z >= this.z\n            )\n                return true\n            else\n                return false\n        }\n    }\n\n    Proton.Box = Box;\n\n\n\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Behaviour(life, easing) {\n        /**\n         * The behaviour's id;\n         * @property id\n         * @type {String} id\n         */\n        this.id = 'Behaviour_' + Behaviour.id++;\n        this.life = Proton.Util.initValue(life, Infinity);\n\n        /**\n         * The behaviour's decaying trend, for example Proton.easeOutQuart;\n         * @property easing\n         * @type {String}\n         * @default Proton.easeLinear\n         */\n        this.easing = Proton.Util.initValue(easing, Proton.ease.setEasingByName(Proton.ease.easeLinear));\n        this.age = 0;\n        this.energy = 1;\n        /**\n         * The behaviour is Dead;\n         * @property dead\n         * @type {Boolean}\n         */\n        this.dead = false;\n\n        /**\n         * The behaviour name;\n         * @property name\n         * @type {string}\n         */\n\n        this.name = 'Behaviour';\n    }\n\n    Behaviour.id = 0;\n\n\n    Behaviour.prototype = {\n        /**\n         * Reset this behaviour's parameters\n         *\n         * @method reset\n         * @param {Number} this behaviour's life\n         * @param {String} this behaviour's easing\n         */\n        reset: function(life, easing) {\n            this.life = Proton.Util.initValue(life, Infinity);\n            this.easing = Proton.Util.initValue(easing, Proton.ease.setEasingByName(Proton.ease.easeLinear));\n        },\n        /**\n         * Normalize a force by 1:100;\n         *\n         * @method normalizeForce\n         * @param {Proton.Vector2D} force \n         */\n        normalizeForce: function(force) {\n            return force.scalar(Proton.MEASURE);\n        },\n\n        /**\n         * Normalize a value by 1:100;\n         *\n         * @method normalizeValue\n         * @param {Number} value\n         */\n        normalizeValue: function(value) {\n            return value * Proton.MEASURE;\n        },\n\n        /**\n         * Initialize the behaviour's parameters for all particles\n         *\n         * @method initialize\n         * @param {Proton.Particle} particle\n         */\n        initialize: function(particle) {},\n\n        /**\n         * Apply this behaviour for all particles every time\n         *\n         * @method applyBehaviour\n         * @param {Proton.Particle} particle\n         * @param {Number} the integrate time 1/ms\n         * @param {Int} the particle index\n         */\n        applyBehaviour: function(particle, time, index) {\n            if (this.dead) return;\n\n            this.age += time;\n            if (this.age >= this.life) {\n                this.energy = 0;\n                this.dead = true;\n                return;\n            }\n\n            var scale = this.easing(particle.age / particle.life);\n            this.energy = Math.max(1 - scale, 0);\n        },\n\n        /**\n         * Destory this behaviour\n         * @method destroy\n         */\n        destroy: function() {\n\n        }\n    };\n\n    Proton.Behaviour = Behaviour;\n\n\n\n    /**\n     * The number of particles per second emission (a [particle]/b [s]);\n     * @class Proton.Rate\n     * @constructor\n     * @param {Array or Number or Proton.Span} numPan the number of each emission;\n     * @param {Array or Number or Proton.Span} timePan the time of each emission;\n     * for example: new Proton.Rate(new Proton.Span(10, 20), new Proton.Span(.1, .25));\n     */\n     \n    function Rate(numPan, timePan) {\n        this.numPan = Proton.createSpan(Proton.Util.initValue(numPan, 1));\n        this.timePan = Proton.createSpan(Proton.Util.initValue(timePan, 1));\n\n        this.startTime = 0;\n        this.nextTime = 0;\n        this.init();\n    }\n\n    Rate.prototype = {\n        init: function() {\n            this.startTime = 0;\n            this.nextTime = this.timePan.getValue();\n        },\n\n        getValue: function(time) {\n            this.startTime += time;\n\n            if (this.startTime >= this.nextTime) {\n                this.init();\n\n                if (this.numPan.b == 1) {\n                    if (this.numPan.getValue(\"Float\") > 0.5)\n                        return 1;\n                    else\n                        return 0;\n                } else {\n                    return this.numPan.getValue(\"Int\");\n                }\n            }\n\n            return 0;\n        }\n    }\n\n    Proton.Rate = Rate;\n\n\n\n    function Initialize() {\n        this.name = \"Initialize\";\n    }\n\n\n    Initialize.prototype.reset = function() {\n\n    }\n\n    Initialize.prototype.init = function(emitter, particle) {\n        if (particle) {\n            this.initialize(particle);\n        } else {\n            this.initialize(emitter);\n        }\n    };\n\n    ///sub class init\n    Initialize.prototype.initialize = function(target) {};\n    Proton.Initialize = Initialize;\n\n\n\n    var InitializeUtil = {\n\n        initialize: function(emitter, particle, initializes) {\n            var i = initializes.length;\n            while (i--) {\n                var initialize = initializes[i];\n                if (initialize instanceof Proton.Initialize)\n                    initialize.init(emitter, particle);\n                else\n                    InitializeUtil.init(emitter, particle, initialize);\n            }\n\n            InitializeUtil.bindEmitter(emitter, particle);\n        },\n\n        //////////////////////init//////////////////////\n        init: function(emitter, particle, initialize) {\n            Proton.Util.setPrototypeByObj(particle, initialize);\n            Proton.Util.setVectorByObj(particle, initialize);\n        },\n\n        bindEmitter: function(emitter, particle) {\n            if (emitter.bindEmitter) {\n                particle.p.add(emitter.p);\n                particle.v.add(emitter.v);\n                particle.a.add(emitter.a);\n                particle.v.applyEuler(emitter.rotation);\n            }\n        }\n    }\n\n    Proton.InitializeUtil = InitializeUtil;\n\n\n\n    /**\n     * Life is init particle's Life\n     * @param {Number} a - the Life's start point\n     * @param {Number} b - the Life's end point  \n     * @param {String} c - span's center \n     * @example \n     * var life = new Proton.Life(3,5);\n     * or\n     * var life = new Proton.Life(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Life(a, b, c) {\n        Life._super_.call(this);\n        this.lifePan = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Life, Proton.Initialize);\n    Life.prototype.initialize = function(target) {\n        if (this.lifePan.a == Infinity || this.lifePan.a == \"infi\")\n            target.life = Infinity;\n        else\n            target.life = this.lifePan.getValue();\n    };\n\n\n    Proton.Life = Life;\n\n\n\n    /**\n     * Position is init particle's Position\n     * @param {Zone} zone - the Position zone\n     * @example \n     * var Position = new Proton.Position(new Proton.PointZone(30,100,0));\n     * or\n     * var Position = new Proton.Position(Infinity);\n     * @extends {Proton.Initialize}\n     * @constructor\n     */\n    function Position() {\n        Position._super_.call(this);\n        this.reset.apply(this, arguments);\n    }\n\n\n    Proton.Util.inherits(Position, Proton.Initialize);\n    Position.prototype.reset = function() {\n        if (!this.zones) this.zones = [];\n        else this.zones.length = 0;\n\n        var args = Array.prototype.slice.call(arguments);\n        this.zones = this.zones.concat(args);\n    };\n\n    Position.prototype.addZone = function() {\n        var args = Array.prototype.slice.call(arguments);\n        this.zones = this.zones.concat(args);\n    };\n\n    Position.prototype.initialize = function() {\n        var zone;\n        return function(target) {\n            var zone = this.zones[(Math.random() * this.zones.length) >> 0];\n            zone.getPosition();\n\n            target.p.x = zone.vector.x;\n            target.p.y = zone.vector.y;\n            target.p.z = zone.vector.z;\n        }\n    }();\n\n\n    Proton.Position = Position;\n    Proton.P = Position;\n\n\n\n\n    /**\n     * Velocity is init particle's Velocity\n     * @param {Number} a - the Life's start point\n     * @param {Number} b - the Life's end point  \n     * @param {String} c - span's center \n     * @example \n     * var life = new Proton.Life(3,5);\n     * or\n     * var life = new Proton.Life(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    //radius and tha\n    function Velocity(a, b, c) {\n        Velocity._super_.call(this);\n        this.reset(a, b, c);\n        this.dirVec = new Proton.Vector3D(0, 0, 0);\n\n        this.name = \"Velocity\";\n    }\n\n    Proton.Util.inherits(Velocity, Proton.Initialize);\n\n    Velocity.prototype.reset = function(a, b, c) {\n        //[vector,tha]\n        if (a instanceof Proton.Vector3D) {\n            this.radiusPan = Proton.createSpan(1);\n            this.dir = a.clone();\n            this.tha = b * Proton.DR;\n            this._useV = true;\n        }\n\n        //[polar,tha]\n        else if (a instanceof Proton.Polar3D) {\n            this.tha = b * Proton.DR;\n            this.dirVec = a.toVector3D();\n            this._useV = false;\n        }\n\n        //[radius,vector,tha]\n        else {\n            this.radiusPan = Proton.createSpan(a);\n            this.dir = b.clone().normalize();\n            this.tha = c * Proton.DR;\n            this._useV = true;\n        }\n    };\n\n    Velocity.prototype.normalize = function(vr) {\n        return vr * Proton.MEASURE;\n    }\n\n    Velocity.prototype.initialize = function() {\n        var tha;\n        var normal = new Proton.Vector3D(0, 0, 1);\n        var v = new Proton.Vector3D(0, 0, 0);\n\n        return function initialize(target) {\n            tha = this.tha * Math.random();\n            this._useV && this.dirVec.copy(this.dir).scalar(this.radiusPan.getValue());\n\n            Proton.MathUtils.getNormal(this.dirVec, normal);\n            v.copy(this.dirVec).applyAxisAngle(normal, tha);\n            v.applyAxisAngle(this.dirVec.normalize(), Math.random() * Proton.PI * 2);\n\n            //use  axisRotate methods\n            //Proton.MathUtils.axisRotate(this.v1, this.dirVec, normal, tha);\n            //Proton.MathUtils.axisRotate(this.v2, this.v1, this.dirVec.normalize(), Math.random() * Proton.PI * 2);\n            target.v.copy(v);\n            return this;\n        };\n    }()\n\n    Proton.Velocity = Velocity;\n    Proton.V = Velocity;\n\n\n\n    /**\n     * Mass is init particle's Mass\n     * @param {Number} a - the Mass's start point\n     * @param {Number} b - the Mass's end point  \n     * @param {String} c - span's center \n     * @example \n     * var Mass = new Proton.Mass(3,5);\n     * or\n     * var Mass = new Proton.Mass(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Mass(a, b, c) {\n        Mass._super_.call(this);\n        this.massPan = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Mass, Proton.Initialize);\n    Mass.prototype.initialize = function(target) {\n        target.mass = this.massPan.getValue();\n    };\n\n    Proton.Mass = Mass;\n\n\n\n\n    /**\n     * Radius is init particle's Radius\n     * @param {Number} a - the Radius's start point\n     * @param {Number} b - the Radius's end point  \n     * @param {String} c - span's center \n     * @example \n     * var Radius = new Proton.Radius(3,5);\n     * or\n     * var Radius = new Proton.Radius(3,1,\"center\");\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Radius(a, b, c) {\n        Radius._super_.call(this);\n        this.radius = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Radius, Proton.Initialize);\n    Radius.prototype.reset = function(a, b, c) {\n        this.radius = Proton.createSpan(a, b, c);\n    };\n\n    Radius.prototype.initialize = function(particle) {\n        particle.radius = this.radius.getValue();\n        particle.transform.oldRadius = particle.radius;\n    };\n\n    Proton.Radius = Radius;\n\n\n\n    function Body(body, w, h) {\n        Body._super_.call(this);\n        this.body = Proton.createArraySpan(body);\n        this.w = w;\n        this.h = Proton.Util.initValue(h, this.w);\n    }\n\n    Proton.Util.inherits(Body, Proton.Initialize);\n\n    Body.prototype.initialize = function(particle) {\n        var body = this.body.getValue();\n        if (!!this.w) {\n            particle.body = {\n                width: this.w,\n                height: this.h,\n                body: body\n            };\n        } else {\n            particle.body = body;\n        }\n    };\n\n    Proton.Body = Body;\n\n\n\n\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Force(fx, fy, fz, life, easing) {\n        Force._super_.call(this, life, easing);\n        Force.prototype.reset.call(this, fx, fy, fz);\n        this.name = \"Force\";\n    }\n\n    Proton.Util.inherits(Force, Proton.Behaviour);\n    Force.prototype.reset = function(fx, fy, fz) {\n        this.force = this.normalizeForce(new Proton.Vector3D(fx, fy, fz));\n        this.force.id = Math.random();\n    }\n\n    Force.prototype.applyBehaviour = function(particle, time, index) {\n        Force._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        particle.a.add(this.force);\n    };\n\n    Proton.F = Proton.Force = Force;\n\n\n\n\tfunction Attraction(targetPosition, force, radius, life, easing) {\n\t\tAttraction._super_.call(this, life, easing);\n\t\tthis.targetPosition = Proton.Util.initValue(targetPosition, new Proton.Vector3D);\n\t\tthis.radius = Proton.Util.initValue(radius, 1000);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tthis.radiusSq = this.radius * this.radius\n\t\tthis.attractionForce = new Proton.Vector3D();\n\t\tthis.lengthSq = 0;\n\t\tthis.name = \"Attraction\";\n\t}\n\n\n\tProton.Util.inherits(Attraction, Proton.Behaviour);\n\tAttraction.prototype.reset = function(targetPosition, force, radius, life, easing) {\n\t\tthis.targetPosition = Proton.Util.initValue(targetPosition, new Proton.Vector3D);\n\t\tthis.radius = Proton.Util.initValue(radius, 1000);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tthis.radiusSq = this.radius * this.radius\n\t\tthis.attractionForce = new Proton.Vector3D();\n\t\tthis.lengthSq = 0;\n\t\tif (life)\n\t\t\tAttraction._super_.prototype.reset.call(this, life, easing);\n\t}\n\n\tAttraction.prototype.applyBehaviour = function(particle, time, index) {\n\t\tAttraction._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\t\tthis.attractionForce.copy(this.targetPosition);\n\t\tthis.attractionForce.sub(particle.p);\n\t\tthis.lengthSq = this.attractionForce.lengthSq();\n\t\tif (this.lengthSq > 0.000004 && this.lengthSq < this.radiusSq) {\n\t\t\tthis.attractionForce.normalize();\n\t\t\tthis.attractionForce.scalar(1 - this.lengthSq / this.radiusSq);\n\t\t\tthis.attractionForce.scalar(this.force);\n\t\t\tparticle.a.add(this.attractionForce);\n\t\t}\n\t};\n\n\tProton.Attraction = Attraction;\n\n\n\n\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function RandomDrift(driftX, driftY, driftZ, delay, life, easing) {\n        RandomDrift._super_.call(this, life, easing);\n        this.reset(driftX, driftY, driftZ, delay);\n        this.time = 0;\n        this.name = \"RandomDrift\";\n    }\n\n\n    Proton.Util.inherits(RandomDrift, Proton.Behaviour);\n    RandomDrift.prototype.reset = function(driftX, driftY, driftZ, delay, life, easing) {\n        this.randomFoce = this.normalizeForce(new Proton.Vector3D(driftX, driftY, driftZ));\n        this.delayPan = Proton.createSpan(delay || .03);\n        this.time = 0;\n        life && RandomDrift._super_.prototype.reset.call(this, life, easing);\n    }\n\n    RandomDrift.prototype.applyBehaviour = function(particle, time, index) {\n        RandomDrift._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        this.time += time;\n        if (this.time >= this.delayPan.getValue()) {\n            var ax = Proton.MathUtils.randomAToB(-this.randomFoce.x, this.randomFoce.x);\n            var ay = Proton.MathUtils.randomAToB(-this.randomFoce.y, this.randomFoce.y);\n            var az = Proton.MathUtils.randomAToB(-this.randomFoce.z, this.randomFoce.z);\n            particle.a.addValue(ax, ay, az);\n            this.time = 0;\n        };\n    };\n\n    Proton.RandomDrift = RandomDrift;\n\n\n\n\tfunction Repulsion(targetPosition, force, radius, life, easing) {\n\t\tRepulsion._super_.call(this, targetPosition, force, radius, life, easing);\n\t\tthis.force *= -1;\n\t\tthis.name = \"Repulsion\";\n\t}\n\n\n\tProton.Util.inherits(Repulsion, Proton.Attraction);\n\tRepulsion.prototype.reset = function(targetPosition, force, radius, life, easing) {\n\t\tRepulsion._super_.prototype.reset.call(this, targetPosition, force, radius, life, easing);\n\t\tthis.force *= -1;\n\t}\n\tProton.Repulsion = Repulsion;\n\n\n\n\n    function Gravity(g, life, easing) {\n        Gravity._super_.call(this, 0, -g, 0, life, easing);\n        this.name = \"Gravity\";\n    }\n\n    Proton.Util.inherits(Gravity, Proton.Force);\n\n    Gravity.prototype.reset = function(g, life, easing) {\n        Gravity._super_.prototype.reset.call(this, 0, -g, 0, life, easing);\n    }\n\n    Proton.Gravity = Gravity;\n    Proton.G = Gravity;\n\n\n\n    /**\n     * The Scale class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n    //can use Collision(emitter,true,function(){}) or Collision();\n    function Collision(emitter, useMass, callback, life, easing) {\n        Collision._super_.call(this, life, easing);\n        this.reset(emitter, useMass, callback);\n        this.name = \"Collision\";\n    }\n\n    Proton.Util.inherits(Collision, Proton.Behaviour);\n    Collision.prototype.reset = function(emitter, useMass, callback, life, easing) {\n        this.emitter = emitter;\n        this.useMass = useMass;\n        this.callback = callback;\n        this.particles = [];\n        this.delta = new Proton.Vector3D();\n        life && Collision._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Collision.prototype.applyBehaviour = function(particle, time, index) {\n        var particles = this.emitter ? this.emitter.particles.slice(index) : this.particles.slice(index);\n        var otherParticle, lengthSq, overlap, distance;\n        var averageMass1, averageMass2;\n        \n        var i = particles.length;\n        while (i--) {\n            otherParticle = particles[i];\n            if (otherParticle == particle) continue;\n            \n            this.delta.copy(otherParticle.p).sub(particle.p);\n            lengthSq = this.delta.lengthSq();\n            distance = particle.radius + otherParticle.radius;\n\n            if (lengthSq <= distance * distance) {\n                overlap = distance - Math.sqrt(lengthSq);\n                overlap += 0.5;\n\n                averageMass1 = this._getAverageMass(particle, otherParticle);\n                averageMass2 = this._getAverageMass(otherParticle, particle);\n\n                particle.p.add(this.delta.clone().normalize().scalar(overlap * -averageMass1));\n                otherParticle.p.add(this.delta.normalize().scalar(overlap * averageMass2));\n\n                this.callback && this.callback(particle, otherParticle);\n            }\n        }\n    };\n\n    Collision.prototype._getAverageMass = function(aPartcile, bParticle) {\n        return this.useMass ? bParticle.mass / (aPartcile.mass + bParticle.mass) : 0.5;\n    }\n\n    Proton.Collision = Collision;\n\n\n\n\n    function CrossZone(a, b, life, easing) {\n        CrossZone._super_.call(this, life, easing);\n        this.reset(a, b);\n        ///dead /bound /cross\n        this.name = \"CrossZone\";\n    }\n\n\n    Proton.Util.inherits(CrossZone, Proton.Behaviour);\n    CrossZone.prototype.reset = function(a, b, life, easing) {\n        var zone, crossType;\n        if (typeof a == \"string\") {\n            crossType = a;\n            zone = b;\n        } else {\n            crossType = b;\n            zone = a;\n        }\n        \n        this.zone = zone;\n        this.zone.crossType = Proton.Util.initValue(crossType, \"dead\");\n        if (life)\n            CrossZone._super_.prototype.reset.call(this, life, easing);\n    }\n\n    CrossZone.prototype.applyBehaviour = function(particle, time, index) {\n        CrossZone._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        this.zone.crossing.call(this.zone, particle);\n    };\n\n    Proton.CrossZone = CrossZone;\n\n\n\n\n    /**\n     * The Alpha class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n\n    function Alpha(a, b, life, easing) {\n        Alpha._super_.call(this, life, easing);\n        this.reset(a, b);\n        /**\n         * The Proton.Behaviour name;\n         * @property name\n         * @type {string}\n         */\n        this.name = \"Alpha\";\n    }\n\n\n    Proton.Util.inherits(Alpha, Proton.Behaviour);\n    Alpha.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createSpan(Proton.Util.initValue(a, 1));\n        this.b = Proton.createSpan(b);\n        life && Alpha._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Alpha.prototype.initialize = function(particle) {\n        particle.useAlpha = true;\n        particle.transform.alphaA = this.a.getValue();\n        if (this._same)\n            particle.transform.alphaB = particle.transform.alphaA;\n        else\n            particle.transform.alphaB = this.b.getValue();\n    };\n\n    Alpha.prototype.applyBehaviour = function(particle, time, index) {\n        Alpha._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        particle.alpha = Proton.MathUtils.lerp(particle.transform.alphaA, particle.transform.alphaB, this.energy);\n        if (particle.alpha < 0.002) particle.alpha = 0;\n    };\n\n    Proton.Alpha = Alpha;\n\n\n\n    /**\n     * The Scale class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n\n    function Scale(a, b, life, easing) {\n        Scale._super_.call(this, life, easing);\n        this.reset(a, b);\n        this.name = \"Scale\";\n    }\n\n\n    Proton.Util.inherits(Scale, Proton.Behaviour);\n    Scale.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createSpan(Proton.Util.initValue(a, 1));\n        this.b = Proton.createSpan(b);\n\n        life && Scale._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Scale.prototype.initialize = function(particle) {\n        particle.transform.scaleA = this.a.getValue();\n        particle.transform.oldRadius = particle.radius;\n        if (this._same)\n            particle.transform.scaleB = particle.transform.scaleA;\n        else\n            particle.transform.scaleB = this.b.getValue();\n\n    };\n\n    Scale.prototype.applyBehaviour = function(particle, time, index) {\n        Scale._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        particle.scale = Proton.MathUtils.lerp(particle.transform.scaleA, particle.transform.scaleB, this.energy);\n\n        if (particle.scale < 0.0005) particle.scale = 0;\n        particle.radius = particle.transform.oldRadius * particle.scale;\n    };\n\n    Proton.Scale = Scale;\n\n\n\n\n    /* The Rotate class is the base\n     * for the other Behaviour\n     *\n     * @class Behaviour * @constructor \n     * @example new Proton.Rotate(Proton.createSpan(-1,1),Proton.createSpan(-1,1),Proton.createSpan(-1,1)); \n     * @example new Proton.Rotate(); \n     * @example new Proton.Rotate(\"random\"); \n     */\n\n    function Rotate(x, y, z, life, easing) {\n        Rotate._super_.call(this, life, easing);\n        this.reset(x, y, z);\n        this.name = \"Rotate\";\n    }\n\n    Proton.Util.inherits(Rotate, Proton.Behaviour);\n    Rotate.prototype.reset = function(a, b, c, life, easing) {\n        this.a = a || 0;\n        this.b = b || 0;\n        this.c = c || 0;\n\n        if (a === undefined || a == \"same\") {\n            this._type = \"same\";\n        } else if (b == undefined) {\n            this._type = \"set\";\n        } else if (c === undefined) {\n            this._type = \"to\";\n        } else {\n            this._type = \"add\";\n            this.a = Proton.createSpan(this.a * Proton.DR);\n            this.b = Proton.createSpan(this.b * Proton.DR);\n            this.c = Proton.createSpan(this.c * Proton.DR);\n        }\n\n        life && Rotate._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Rotate.prototype.initialize = function(particle) {\n        switch (this._type) {\n            case \"same\":\n                break;\n\n            case \"set\":\n                this._setRotation(particle.rotation, this.a);\n                break;\n\n            case \"to\":\n                particle.transform.fR = particle.transform.fR || new Proton.Vector3D;\n                particle.transform.tR = particle.transform.tR || new Proton.Vector3D;\n                this._setRotation(particle.transform.fR, this.a);\n                this._setRotation(particle.transform.tR, this.b);\n                break;\n\n            case \"add\":\n                particle.transform.addR = new Proton.Vector3D(this.a.getValue(), this.b.getValue(), this.c.getValue());\n                break;\n        }\n    };\n\n    Rotate.prototype._setRotation = function(vec3, value) {\n        vec3 = vec3 || new Proton.Vector3D;\n        if (value == \"random\") {\n            var x = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            var y = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            var z = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            vec3.set(x, y, z);\n        } else if (value instanceof Proton.Vector3D) {\n            vec3.copy(value);\n        }\n    };\n\n    Rotate.prototype.applyBehaviour = function(particle, time, index) {\n        Rotate._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        switch (this._type) {\n            case \"same\":\n                if (!particle.rotation) particle.rotation = new Proton.Vector3D;\n                particle.rotation.eulerFromDir(particle.v);\n                //http://stackoverflow.com/questions/21622956/how-to-convert-direction-vector-to-euler-angles\n                //console.log(particle.rotation);\n                break;\n\n            case \"set\":\n                //\n                break;\n\n            case \"to\":\n                particle.rotation.x = Proton.MathUtils.lerp(particle.transform.fR.x, particle.transform.tR.x, this.energy);\n                particle.rotation.y = Proton.MathUtils.lerp(particle.transform.fR.y, particle.transform.tR.y, this.energy);\n                particle.rotation.z = Proton.MathUtils.lerp(particle.transform.fR.z, particle.transform.tR.z, this.energy);\n                break;\n\n            case \"add\":\n                particle.rotation.add(particle.transform.addR);\n                break;\n        }\n    };\n\n    Proton.Rotate = Rotate;\n\n\n\n    /**\n     * The Scale class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n    function Color(a, b, life, easing) {\n        Color._super_.call(this, life, easing);\n        this.reset(a, b);\n        this.name = \"Color\";\n    }\n\n\n    Proton.Util.inherits(Color, Proton.Behaviour);\n    Color.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createArraySpan(a);\n        this.b = Proton.createArraySpan(b);\n        life && Color._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Color.prototype.initialize = function(particle) {\n        particle.transform.colorA = Proton.ColorUtil.getRGB(this.a.getValue());\n\n        particle.useColor = true;\n        if (this._same)\n            particle.transform.colorB = particle.transform.colorA;\n        else\n            particle.transform.colorB = Proton.ColorUtil.getRGB(this.b.getValue());\n    };\n\n    Color.prototype.applyBehaviour = function(particle, time, index) {\n        Color._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        if (!this._same) {\n            particle.color.r = Proton.MathUtils.lerp(particle.transform.colorA.r, particle.transform.colorB.r, this.energy) ;\n            particle.color.g = Proton.MathUtils.lerp(particle.transform.colorA.g, particle.transform.colorB.g, this.energy) ;\n            particle.color.b = Proton.MathUtils.lerp(particle.transform.colorA.b, particle.transform.colorB.b, this.energy) ;\n        } else {\n            particle.color.r = particle.transform.colorA.r;\n            particle.color.g = particle.transform.colorA.g;\n            particle.color.b = particle.transform.colorA.b;\n        }\n    };\n\n\n    Proton.Color = Color;\n\n\n\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Spring(x, y, z, spring, friction, life, easing) {\n        Spring._super_.call(this, life, easing);\n        Spring.prototype.reset(x, y, z, spring, friction);\n        this.name = \"Spring\";\n    }\n\n    Proton.Util.inherits(Spring, Proton.Behaviour);\n    Spring.prototype.reset = function(x, y, z, spring, friction) {\n        if (!this.pos)\n            this.pos = new Proton.Vector3D(x, y, z);\n        else\n            this.pos.set(x, y, z);\n        this.spring = spring || .1;\n        this.friction = friction || .98;\n    }\n\n    Spring.prototype.applyBehaviour = function(particle, time, index) {\n        Spring._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        particle.v.x += (this.pos.x - particle.p.x) * this.spring;\n        particle.v.y += (this.pos.y - particle.p.y) * this.spring;\n        particle.v.z += (this.pos.z - particle.p.z) * this.spring;\n\n    };\n\n\n    Proton.Spring = Spring;\n\n\n\n    function Emitter(pObj) {\n        this.initializes = [];\n        this.particles = [];\n        this.behaviours = [];\n        this.currentEmitTime = 0;\n        this.totalEmitTimes = -1;\n\n        /**\n         * @property {Number} damping -The friction coefficient for all particle emit by This;\n         * @default 0.006\n         */\n        this.damping = .006;\n        /**\n         * If bindEmitter the particles can bind this emitter's property;\n         * @property bindEmitter\n         * @type {Boolean}\n         * @default true\n         */\n        this.bindEmitter = true;\n        /**\n         * The number of particles per second emit (a [particle]/b [s]);\n         * @property rate\n         * @type {Rate}\n         * @default Rate(1, .1)\n         */\n        this.rate = new Proton.Rate(1, .1);\n        Emitter._super_.call(this, pObj);\n        /**\n         * The emitter's id;\n         * @property id\n         * @type {String} id\n         */\n        this.id = 'emitter_' + Emitter.ID++;\n        this.cID = 0;\n        this.name = 'Emitter';\n    };\n    Emitter.ID = 0;\n\n    Proton.Util.inherits(Emitter, Proton.Particle);\n    Proton.EventDispatcher.initialize(Emitter.prototype);\n\n    /**\n     * start emit particle\n     * @method emit\n     * @param {Number} totalEmitTimes total emit times;\n     * @param {String} life the life of this emitter\n     */\n    Emitter.prototype.emit = function(totalEmitTimes, life) {\n        this.currentEmitTime = 0;\n        this.totalEmitTimes = Proton.Util.initValue(totalEmitTimes, Infinity);\n\n        if (life == true || life == 'life' || life == 'destroy') {\n            this.life = totalEmitTimes == 'once' ? 1 : this.totalEmitTimes;\n        } else if (!isNaN(life)) {\n            this.life = life;\n        }\n\n        this.rate.init();\n    };\n\n    /**\n     * stop emiting\n     * @method stopEmit\n     */\n    Emitter.prototype.stopEmit = function() {\n        this.totalEmitTimes = -1;\n        this.currentEmitTime = 0;\n    };\n\n    /**\n     * remove current all particles\n     * @method removeAllParticles\n     */\n    Emitter.prototype.removeAllParticles = function() {\n        var i = this.particles.length;\n        while (i--) this.particles[i].dead = true;\n    };\n\n    /**\n     * create single particle;\n     * \n     * can use emit({x:10},new Gravity(10),{'particleUpdate',fun}) or emit([{x:10},new Initialize],new Gravity(10),{'particleUpdate',fun})\n     * @method removeAllParticles\n     */\n    Emitter.prototype.createParticle = function(initialize, behaviour) {\n        var particle = this.parent.pool.get(Proton.Particle);\n        this.setupParticle(particle, initialize, behaviour);\n        this.parent && this.parent.dispatchEvent(\"PARTICLE_CREATED\", particle);\n        Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_CREATED\", particle);\n\n        return particle;\n    };\n    /**\n     * add initialize to this emitter\n     * @method addSelfInitialize\n     */\n    Emitter.prototype.addSelfInitialize = function(pObj) {\n        if (pObj['init']) {\n            pObj.init(this);\n        } else {\n            this.initAll();\n        }\n    };\n\n\n    /**\n     * add the Initialize to particles;\n     * \n     * you can use initializes array:for example emitter.addInitialize(initialize1,initialize2,initialize3);\n     * @method addInitialize\n     * @param {Initialize} initialize like this new Radius(1, 12)\n     */\n    Emitter.prototype.addInitialize = function() {\n        var i = arguments.length;\n        while (i--) this.initializes.push(arguments[i]);\n    };\n\n\n    /**\n     * remove the Initialize\n     * @method removeInitialize\n     * @param {Initialize} initialize a initialize\n     */\n    Emitter.prototype.removeInitialize = function(initializer) {\n        var index = this.initializes.indexOf(initializer);\n        if (index > -1) this.initializes.splice(index, 1);\n    };\n\n    /**\n     * remove all Initializes\n     * @method removeInitializers\n     */\n    Emitter.prototype.removeInitializers = function() {\n        Proton.Util.destroyArray(this.initializes);\n    };\n    /**\n     * add the Behaviour to particles;\n     * \n     * you can use Behaviours array:emitter.addBehaviour(Behaviour1,Behaviour2,Behaviour3);\n     * @method addBehaviour\n     * @param {Behaviour} behaviour like this new Color('random')\n     */\n    Emitter.prototype.addBehaviour = function() {\n        var i = arguments.length;\n        while (i--) this.behaviours.push(arguments[i]);\n    };\n    /**\n     * remove the Behaviour\n     * @method removeBehaviour\n     * @param {Behaviour} behaviour a behaviour\n     */\n    Emitter.prototype.removeBehaviour = function(behaviour) {\n        var index = this.behaviours.indexOf(behaviour);\n        if (index > -1) this.behaviours.splice(index, 1);\n    };\n    /**\n     * remove all behaviours\n     * @method removeAllBehaviours\n     */\n    Emitter.prototype.removeAllBehaviours = function() {\n        Proton.Util.destroyArray(this.behaviours);\n    };\n\n    Emitter.prototype.integrate = function(time) {\n        var damping = 1 - this.damping;\n        Proton.integrator.integrate(this, time, damping);\n\n        var i = this.particles.length;\n        while (i--) {\n            var particle = this.particles[i];\n            particle.update(time, i);\n            Proton.integrator.integrate(particle, time, damping);\n\n            this.parent && this.parent.dispatchEvent(\"PARTICLE_UPDATE\", particle);\n            Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_UPDATE\", particle);\n        }\n    };\n\n    Emitter.prototype.emitting = function(time) {\n        if (this.totalEmitTimes == 'once') {\n            var i = this.rate.getValue(99999);\n            if (i > 0) this.cID = i;\n            while (i--) this.createParticle();\n            this.totalEmitTimes = 'none';\n\n        } else if (!isNaN(this.totalEmitTimes)) {\n            this.currentEmitTime += time;\n            if (this.currentEmitTime < this.totalEmitTimes) {\n                var i = this.rate.getValue(time);\n                if (i > 0) this.cID = i;\n                while (i--) this.createParticle();\n            }\n        }\n    }\n\n    Emitter.prototype.update = function(time) {\n        this.age += time;\n        if (this.dead || this.age >= this.life) {\n            this.destroy();\n        }\n\n        this.emitting(time);\n        this.integrate(time);\n\n        var particle, i = this.particles.length;\n        while (i--) {\n            particle = this.particles[i];\n            if (particle.dead) {\n                this.parent && this.parent.dispatchEvent(\"PARTICLE_DEAD\", particle);\n                Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_DEAD\", particle);\n\n                this.parent.pool.expire(particle.reset());\n                this.particles.splice(i, 1);\n            }\n        }\n    };\n\n    Emitter.prototype.setupParticle = function(particle, initialize, behaviour) {\n        var initializes = this.initializes;\n        var behaviours = this.behaviours;\n\n        if (initialize) {\n            if (Proton.Util.isArray(initialize))\n                initializes = initialize;\n            else\n                initializes = [initialize];\n        }\n\n        if (behaviour) {\n            if (Proton.Util.isArray(behaviour))\n                behaviours = behaviour;\n            else\n                behaviours = [behaviour];\n        }\n\n        Proton.InitializeUtil.initialize(this, particle, initializes);\n        particle.addBehaviours(behaviours);\n        particle.parent = this;\n        this.particles.push(particle);\n    };\n\n    /**\n     * Destory this Emitter\n     * @method destroy\n     */\n    Emitter.prototype.destroy = function() {\n        this.dead = true;\n        this.energy = 0;\n        this.totalEmitTimes = -1;\n\n        if (this.particles.length == 0) {\n            this.removeInitializers();\n            this.removeAllBehaviours();\n\n            this.parent && this.parent.removeEmitter(this);\n        }\n    }\n\n\n    Proton.Emitter = Emitter;\n\n\n\n    /**\n     * The BehaviourEmitter class inherits from Proton.Emitter\n     *\n     * use the BehaviourEmitter you can add behaviours to self;\n     * @class Proton.BehaviourEmitter\n     * @constructor\n     * @param {Object} pObj the parameters object;\n     */\n    function BehaviourEmitter(pObj) {\n        this.selfBehaviours = [];\n        BehaviourEmitter._super_.call(this, pObj);\n    };\n\n    Proton.Util.inherits(BehaviourEmitter, Proton.Emitter);\n    /**\n     * add the Behaviour to emitter;\n     *\n     * you can use Behaviours array:emitter.addSelfBehaviour(Behaviour1,Behaviour2,Behaviour3);\n     * @method addSelfBehaviour\n     * @param {Proton.Behaviour} behaviour like this new Proton.Color('random')\n     */\n    BehaviourEmitter.prototype.addSelfBehaviour = function() {\n        var length = arguments.length,\n            i;\n        for (i = 0; i < length; i++) {\n            this.selfBehaviours.push(arguments[i]);\n        }\n    };\n    /**\n     * remove the Behaviour for self\n     * @method removeSelfBehaviour\n     * @param {Proton.Behaviour} behaviour a behaviour\n     */\n    BehaviourEmitter.prototype.removeSelfBehaviour = function(behaviour) {\n        var index = this.selfBehaviours.indexOf(behaviour);\n        if (index > -1) this.selfBehaviours.splice(index, 1);\n    };\n\n    BehaviourEmitter.prototype.update = function(time) {\n        BehaviourEmitter._super_.prototype.update.call(this, time);\n\n        if (!this.sleep) {\n            var length = this.selfBehaviours.length,\n                i;\n            for (i = 0; i < length; i++) {\n                this.selfBehaviours[i].applyBehaviour(this, time, i)\n            }\n        }\n    }\n\n    Proton.BehaviourEmitter = BehaviourEmitter;\n\n\n\n    /**\n     * The FollowEmitter class inherits from Proton.Emitter\n     *\n     * use the FollowEmitter will emit particle when mousemoving\n     *\n     * @class Proton.FollowEmitter\n     * @constructor\n     * @param {Element} mouseTarget mouseevent's target;\n     * @param {Number} ease the easing of following speed;\n     * @default 0.7\n     * @param {Object} pObj the parameters object;\n     */\n    function FollowEmitter(mouseTarget, ease, pObj) {\n        this.mouseTarget = Proton.Util.initValue(mouseTarget, window);\n        this.ease = Proton.Util.initValue(ease, .7);\n        this._allowEmitting = false;\n        this.mouse = new Proton.Vector3D();\n        this.initEventHandler();\n\n        FollowEmitter._super_.call(this, pObj);\n    };\n\n    Proton.Util.inherits(FollowEmitter, Proton.Emitter);\n    FollowEmitter.prototype.initEventHandler = function() {\n        var self = this;\n        this.mousemoveHandler = function(e) {\n            self.mousemove.call(self, e);\n        };\n\n        this.mousedownHandler = function(e) {\n            self.mousedown.call(self, e);\n        };\n\n        this.mouseupHandler = function(e) {\n            self.mouseup.call(self, e);\n        };\n        \n        this.mouseTarget.addEventListener('mousemove', this.mousemoveHandler, false);\n    }\n\n    /**\n     * start emit particle\n     * @method emit\n     */\n    FollowEmitter.prototype.emit = function() {\n        this._allowEmitting = true;\n    }\n\n    /**\n     * stop emiting\n     * @method stopEmit\n     */\n    FollowEmitter.prototype.stopEmit = function() {\n        this._allowEmitting = false;\n    }\n\n    FollowEmitter.prototype.setCameraAndCanvas = function(camera, canvas) {\n        this.camera = camera;\n        this.canvas = canvas;\n    }\n\n    FollowEmitter.prototype.setCameraAndRenderer = function(camera, renderer) {\n        this.camera = camera;\n        this.renderer = renderer;\n        this.canvas = renderer.domElement;\n    }\n\n    FollowEmitter.prototype.mousemove = function(e) {\n        var rect = this.canvas.getBoundingClientRect();\n        var x = e.clientX - rect.left;\n        var y = e.clientY - rect.top;\n        var ratio = this.renderer? this.renderer.getPixelRatio() : 1;\n        x *= ratio;\n        y *= ratio;\n\n        this.mouse.x += (x - this.mouse.x) * this.ease;\n        this.mouse.y += (y - this.mouse.y) * this.ease;\n        \n        this.p.copy(Proton.THREEUtil.toSpacePos(this.mouse, this.camera, this.canvas, this.renderer));\n\n        if (this._allowEmitting){\n            FollowEmitter._super_.prototype.emit.call(this, 'once');\n        }\n    };\n\n    /**\n     * Destory this Emitter\n     * @method destroy\n     */\n    FollowEmitter.prototype.destroy = function() {\n        FollowEmitter._super_.prototype.destroy.call(this);\n        this.mouseTarget.removeEventListener('mousemove', this.mousemoveHandler, false);\n    }\n\n    Proton.FollowEmitter = FollowEmitter;\n\n\n\n    /**\n     * The Ease class provides a collection of easing functions for use with Proton\n     */\n    var ease = ease || {\n        easeLinear: function(value) {\n            return value;\n        },\n\n        easeInQuad: function(value) {\n            return Math.pow(value, 2);\n        },\n\n        easeOutQuad: function(value) {\n            return -(Math.pow((value - 1), 2) - 1);\n        },\n\n        easeInOutQuad: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 2);\n            return -0.5 * ((value -= 2) * value - 2);\n        },\n\n        easeInCubic: function(value) {\n            return Math.pow(value, 3);\n        },\n\n        easeOutCubic: function(value) {\n            return (Math.pow((value - 1), 3) + 1);\n        },\n\n        easeInOutCubic: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 3);\n            return 0.5 * (Math.pow((value - 2), 3) + 2);\n        },\n\n        easeInQuart: function(value) {\n            return Math.pow(value, 4);\n        },\n\n        easeOutQuart: function(value) {\n            return -(Math.pow((value - 1), 4) - 1);\n        },\n\n        easeInOutQuart: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 4);\n            return -0.5 * ((value -= 2) * Math.pow(value, 3) - 2);\n        },\n\n        easeInSine: function(value) {\n            return -Math.cos(value * (Proton.PI / 2)) + 1;\n        },\n\n        easeOutSine: function(value) {\n            return Math.sin(value * (Proton.PI / 2));\n        },\n\n        easeInOutSine: function(value) {\n            return (-0.5 * (Math.cos(Proton.PI * value) - 1));\n        },\n\n        easeInExpo: function(value) {\n            return (value === 0) ? 0 : Math.pow(2, 10 * (value - 1));\n        },\n\n        easeOutExpo: function(value) {\n            return (value === 1) ? 1 : -Math.pow(2, -10 * value) + 1;\n        },\n\n        easeInOutExpo: function(value) {\n            if (value === 0)\n                return 0;\n            if (value === 1)\n                return 1;\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(2, 10 * (value - 1));\n            return 0.5 * (-Math.pow(2, -10 * --value) + 2);\n        },\n\n        easeInCirc: function(value) {\n            return -(Math.sqrt(1 - (value * value)) - 1);\n        },\n\n        easeOutCirc: function(value) {\n            return Math.sqrt(1 - Math.pow((value - 1), 2));\n        },\n\n        easeInOutCirc: function(value) {\n            if ((value /= 0.5) < 1)\n                return -0.5 * (Math.sqrt(1 - value * value) - 1);\n            return 0.5 * (Math.sqrt(1 - (value -= 2) * value) + 1);\n        },\n\n        easeInBack: function(value) {\n            var s = 1.70158;\n            return (value) * value * ((s + 1) * value - s);\n        },\n\n        easeOutBack: function(value) {\n            var s = 1.70158;\n            return (value = value - 1) * value * ((s + 1) * value + s) + 1;\n        },\n\n        easeInOutBack: function(value) {\n            var s = 1.70158;\n            if ((value /= 0.5) < 1)\n                return 0.5 * (value * value * (((s *= (1.525)) + 1) * value - s));\n            return 0.5 * ((value -= 2) * value * (((s *= (1.525)) + 1) * value + s) + 2);\n        },\n\n        setEasingByName: function(easeName) {\n            if (!!ease[easeName])\n                return ease[easeName];\n            else\n                return ease.easeLinear;\n        }\n    }\n\n\n    for (var id in ease) {\n        if (id != \"setEasingByName\") Proton[id] = ease[id];\n    }\n\n    Proton.ease = ease;\n\n\n\n\n\n    function BaseRender() { this.name = \"BaseRender\"; }\n\n    BaseRender.prototype = {\n        init: function(proton) {\n            var self = this;\n            this.proton = proton;\n            \n            this.proton.addEventListener(\"PROTON_UPDATE\", function(proton) {\n                self.onProtonUpdate.call(self, proton);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_CREATED\", function(particle) {\n                self.onParticleCreated.call(self, particle);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_UPDATE\", function(particle) {\n                self.onParticleUpdate.call(self, particle);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_DEAD\", function(particle) {\n                self.onParticleDead.call(self, particle);\n            });\n        },\n\n        remove: function(proton) {\n            // this.proton.removeEventListener(\"PROTON_UPDATE\", this.onProtonUpdate);\n            // this.proton.removeEventListener(\"PARTICLE_CREATED\", this.onParticleCreated);\n            // this.proton.removeEventListener(\"PARTICLE_UPDATE\", this.onParticleUpdate);\n            // this.proton.removeEventListener(\"PARTICLE_DEAD\", this.onParticleDead);\n            this.proton = null;\n        },\n\n        onParticleCreated: function(particle) {\n\n        },\n\n        onParticleUpdate: function(particle) {\n\n        },\n\n        onParticleDead: function(particle) {\n\n        },\n\n        onProtonUpdate: function(proton) {\n\n        }\n    }\n\n    Proton.BaseRender = BaseRender;\n\n\n\n\n    function MeshRender(container) {\n        MeshRender._super_.call(this);\n        this.container = container;\n\n        this._targetPool = new Proton.Pool();\n        this._materialPool = new Proton.Pool();\n        this._body = new THREE.Mesh(\n            new THREE.BoxGeometry(50, 50, 50),\n            new THREE.MeshLambertMaterial({ color: \"#ff0000\" })\n        );\n        \n        this.name = \"MeshRender\";\n    }\n\n    Proton.Util.inherits(MeshRender, Proton.BaseRender);\n\n    MeshRender.prototype.onProtonUpdate = function() {};\n\n    MeshRender.prototype.onParticleCreated = function(particle) {\n        if (!particle.target) {\n            //set target\n            if (!particle.body) particle.body = this._body;\n            particle.target = this._targetPool.get(particle.body);\n            \n            //set material\n            if (particle.useAlpha || particle.useColor) {\n                particle.target.material.__puid = Proton.PUID.id(particle.body.material);;\n                particle.target.material = this._materialPool.get(particle.target.material);\n            }\n        }\n\n        if (particle.target) {\n            particle.target.position.copy(particle.p);\n            this.container.add(particle.target);\n        }\n    };\n\n    MeshRender.prototype.onParticleUpdate = function(particle) {\n        if (particle.target) {\n            particle.target.position.copy(particle.p);\n            particle.target.rotation.set(particle.rotation.x, particle.rotation.y, particle.rotation.z);\n            this.scale(particle);\n\n            if (particle.useAlpha) {\n                particle.target.material.opacity = particle.alpha;\n                particle.target.material.transparent = true;\n            }\n\n            if (particle.useColor) {\n                particle.target.material.color.copy(particle.color);\n            }\n        }\n    };\n\n    MeshRender.prototype.scale = function(particle) {\n        particle.target.scale.set(particle.scale, particle.scale, particle.scale);\n    }\n\n    MeshRender.prototype.onParticleDead = function(particle) {\n        if (particle.target) {\n            if (particle.useAlpha || particle.useColor)\n                this._materialPool.expire(particle.target.material);\n\n            this._targetPool.expire(particle.target);\n            this.container.remove(particle.target);\n            particle.target = null;\n        }\n    };\n\n    Proton.MeshRender = MeshRender;\n\n\n\n\n    function PointsRender(ps) {\n        PointsRender._super_.call(this);\n        this.points = ps;\n        this.name = \"PointsRender\";\n    }\n\n    Proton.Util.inherits(PointsRender, Proton.BaseRender);\n\n    PointsRender.prototype.onProtonUpdate = function() {\n        \n    };\n\n    PointsRender.prototype.onParticleCreated = function(particle) {\n        if (!particle.target) {\n            particle.target = new THREE.Vector3();\n        }\n\n        particle.target.copy(particle.p);\n        this.points.geometry.vertices.push(particle.target);\n    };\n\n    PointsRender.prototype.onParticleUpdate = function(particle) {\n        if (particle.target) {\n            particle.target.copy(particle.p);\n        }\n    };\n\n    PointsRender.prototype.onParticleDead = function(particle) {\n        if (particle.target) {\n            var index = this.points.geometry.vertices.indexOf(particle.target);\n            if (index > -1)\n                this.points.geometry.vertices.splice(index, 1);\n            \n            particle.target = null;\n        }\n    };\n\n    Proton.PointsRender = PointsRender;\n\n\n\n\n    function SpriteRender(container) {\n        SpriteRender._super_.call(this, container);\n\n        this._body = new THREE.Sprite(new THREE.SpriteMaterial({ color: 0xffffff }));\n        this.name = \"SpriteRender\";\n    }\n\n    Proton.Util.inherits(SpriteRender, Proton.MeshRender);\n\n    SpriteRender.prototype.scale = function(particle) {\n        particle.target.scale.set(particle.scale * particle.radius, particle.scale * particle.radius, 1);\n    };\n\n    Proton.SpriteRender = SpriteRender;\n\n\n\n\n    function CustomRender() {\n        CustomRender._super_.call(this);\n        this.targetPool = new Proton.Pool();\n        this.materialPool = new Proton.Pool();\n        \n        this.name = \"CustomRender\";\n    }\n\n    Proton.Util.inherits(CustomRender, Proton.BaseRender);\n\n    CustomRender.prototype.onProtonUpdate = function() {};\n\n    CustomRender.prototype.onParticleCreated = function(particle) {\n        \n    };\n\n    CustomRender.prototype.onParticleUpdate = function(particle) {\n        \n    };\n\n    CustomRender.prototype.onParticleDead = function(particle) {\n        \n    };\n\n    Proton.CustomRender = CustomRender;\n\n\n\n    /**\n     * Zone is a base class.\n     * @constructor\n     */\n    function Zone() {\n        this.vector = new Proton.Vector3D(0, 0, 0);\n        this.random = 0;\n        this.crossType = \"dead\";\n        this.log = true;\n    }\n\n    Zone.prototype = {\n        getPosition: function() {\n            return null;\n        },\n\n        crossing: function(particle) {\n            switch (this.crossType) {\n                case \"bound\":\n                    this._bound(particle);\n                    break;\n\n                case \"cross\":\n                    this._cross(particle);\n                    break;\n\n                case \"dead\":\n                    this._dead(particle);\n                    break;\n            }\n        },\n\n        _dead: function(particle) {},\n        _bound: function(particle) {},\n        _cross: function(particle) {},\n    };\n\n    Proton.Zone = Zone;\n\n\n\n    /**\n     * LineZone is a 3d line zone\n     * @param {Number|Vector3D} x1 - the line's start point of x value or a Vector3D Object\n     * @param {Number|Vector3D} y1 - the line's start point of y value or a Vector3D Object\n     * @param {Number} z1 - the line's start point of z value \n     * @param {Number} x2 - the line's end point of x value \n     * @param {Number} y2 - the line's end point of y value \n     * @param {Number} z2 - the line's end point of z value \n     * @example \n     * var lineZone = new Proton.LineZone(0,0,0,100,100,0);\n     * or\n     * var lineZone = new Proton.LineZone(new Proton.Vector3D(0,0,0),new Proton.Vector3D(100,100,0));\n     * @extends {Zone}\n     * @constructor\n     */\n    function LineZone(x1, y1, z1, x2, y2, z2) {\n        LineZone._super_.call(this);\n        if (x1 instanceof Proton.Vector3D) {\n            this.x1 = x1.x;\n            this.y1 = x1.y;\n            this.z1 = x1.z;\n\n            this.x2 = x2.x;\n            this.y2 = x2.y;\n            this.z2 = x2.z;\n        } else {\n            this.x1 = x1;\n            this.y1 = y1;\n            this.z1 = z1;\n\n            this.x2 = x2;\n            this.y2 = y2;\n            this.z2 = z2;\n        }\n    }\n\n\n    Proton.Util.inherits(LineZone, Proton.Zone);\n    LineZone.prototype.getPosition = function() {\n        this.random = Math.random();\n        this.vector.x = this.x1 + this.random * (this.x2 - this.x1);\n        this.vector.y = this.y1 + this.random * (this.y2 - this.y1);\n        this.vector.z = this.z1 + this.random * (this.z2 - this.z1);\n        return this.vector;\n    }\n\n    LineZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry LineZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.LineZone = LineZone;\n\n\n\n    /**\n     * SphereZone is a sphere zone\n     * @param {Number|Vector3D} x - the center's x value or a Vector3D Object\n     * @param {Number} y - the center's y value or the Sphere's radius \n     * @param {Number} z - the center's z value \n     * @param {Number} r - the Sphere's radius \n     * @example \n     * var sphereZone = new Proton.SphereZone(0,0,0,100);\n     * var sphereZone = new Proton.SphereZone(new Proton.Vector3D(0,0,0),100);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n    function SphereZone(a, b, c, d) {\n        var x, y, z, r;\n        SphereZone._super_.call(this);\n        if (Proton.Util.isUndefined(b, c, d)) {\n            x = y = z = 0;\n            r = (a || 100);\n        } else {\n            x = a;\n            y = b;\n            z = c;\n            r = d;\n        }\n\n        this.x = x;\n        this.y = x;\n        this.z = x;\n        this.radius = r;\n        this.tha = this.phi = 0;\n    }\n\n    Proton.Util.inherits(SphereZone, Proton.Zone);\n    SphereZone.prototype.getPosition = function() {\n        var tha, phi, r;\n        return function() {\n            this.random = Math.random();\n\n            r = this.random * this.radius;\n            tha = Proton.PI * Math.random(); //[0-pi]\n            phi = Proton.PI * 2 * Math.random(); //[0-2pi]\n\n            this.vector.x = this.x + r * Math.sin(tha) * Math.cos(phi);\n            this.vector.y = this.y + r * Math.sin(phi) * Math.sin(tha);\n            this.vector.z = this.z + r * Math.cos(tha);\n\n            return this.vector;\n        }\n    }();\n\n    SphereZone.prototype._dead = function(particle) {\n        var d = particle.p.distanceTo(this);\n        if (d - particle.radius > this.radius) particle.dead = true;\n    }\n\n    SphereZone.prototype._bound = function() {\n        var normal = new Proton.Vector3D,\n            v = new Proton.Vector3D,\n            k;\n\n        return function(particle) {\n            var d = particle.p.distanceTo(this);\n            if (d + particle.radius >= this.radius) {\n                normal.copy(particle.p).sub(this).normalize();\n                v.copy(particle.v);\n                k = 2 * v.dot(normal);\n                particle.v.sub(normal.scalar(k));\n            }\n        }\n    }();\n\n    SphereZone.prototype._cross = function(particle) {\n        if (this.log) {\n            console.error('Sorry SphereZone does not support _cross method');\n            this.log = false;\n        }\n    }\n\n    Proton.SphereZone = SphereZone;\n\n\n\n\n    /**\n     * MeshZone is a threejs mesh zone\n     * @param {Geometry|Mesh} geometry - a THREE.Geometry or THREE.Mesh object\n     * @example \n     * var geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );\n     * var cylinder = new THREE.Mesh( geometry, material );\n     * var meshZone = new Proton.MeshZone(geometry);\n     * or\n     * var meshZone = new Proton.MeshZone(cylinder);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n\n    function MeshZone(geometry, scale) {\n        MeshZone._super_.call(this);\n        if (geometry instanceof THREE.Geometry) {\n            this.geometry = geometry;\n        } else {\n            this.geometry = geometry.geometry;\n        }\n\n        this.scale = scale || 1;\n    }\n\n    Proton.Util.inherits(MeshZone, Proton.Zone);\n    MeshZone.prototype.getPosition = function() {\n        var vertices = this.geometry.vertices;\n        var rVector = vertices[(vertices.length * Math.random()) >> 0];\n        this.vector.x = rVector.x * this.scale;\n        this.vector.y = rVector.y * this.scale;\n        this.vector.z = rVector.z * this.scale;\n        return this.vector;\n    }\n\n    MeshZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry MeshZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.MeshZone = MeshZone;\n\n\n\n    /**\n     * PointZone is a point zone\n     * @param {Number|Vector3D} x - the center's x value or a Vector3D Object\n     * @param {Number} y - the center's y value\n     * @param {Number} z - the center's z value  \n     * @example \n     * var pointZone = new Proton.PointZone(0,30,10);\n     * or\n     * var pointZone = new Proton.PointZone(new Proton.Vector3D(0,30,10));\n     * @extends {Zone}\n     * @constructor\n     */\n    function PointZone(a, b, c) {\n        var x, y, z;\n        PointZone._super_.call(this);\n\n        if (Proton.Util.isUndefined(a, b, c)) {\n            x = y = z = 0;\n        } else {\n            x = a;\n            y = b;\n            z = c;\n        }\n\n        this.x = x;\n        this.y = y;\n        this.z = z;\n    }\n\n    Proton.Util.inherits(PointZone, Proton.Zone);\n    PointZone.prototype.getPosition = function() {\n        this.vector.x = this.x;\n        this.vector.y = this.y;\n        this.vector.z = this.z;\n        return this.vector;\n    }\n\n    PointZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry PointZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.PointZone = PointZone;\n\n\n\n    /**\n     * BoxZone is a box zone\n     * @param {Number|Proton.Vector3D} x - the position's x value or a Proton.Vector3D Object\n     * @param {Number} y - the position's y value \n     * @param {Number} z - the position's z value \n     * @param {Number} w - the Box's width \n     * @param {Number} h - the Box's height \n     * @param {Number} d - the Box's depth \n     * @example \n     * var boxZone = new Proton.BoxZone(0,0,0,50,50,50);\n     * or\n     * var boxZone = new Proton.BoxZone(new Proton.Proton.Vector3D(0,0,0), 50, 50, 50);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n    function BoxZone(a, b, c, d, e, f) {\n        var x, y, z, w, h, d;\n        BoxZone._super_.call(this);\n\n        if (Proton.Util.isUndefined(b, c, d, e, f)) {\n            x = y = z = 0;\n            w = h = d = (a || 100);\n        } else if (Proton.Util.isUndefined(d, e, f)) {\n            x = y = z = 0;\n            w = a;\n            h = b;\n            d = c;\n        } else {\n            x = a;\n            y = b;\n            z = c;\n            w = d;\n            h = e;\n            d = f;\n        }\n\n        this.x = x;\n        this.y = y;\n        this.z = z;\n        this.width = w;\n        this.height = h;\n        this.depth = d;\n\n        //\n        this.friction = 0.85;\n        this.max = 6;\n    }\n\n    Proton.Util.inherits(BoxZone, Proton.Zone);\n    BoxZone.prototype.getPosition = function() {\n        this.vector.x = this.x + Proton.MathUtils.randomAToB(-.5, .5) * this.width;\n        this.vector.y = this.y + Proton.MathUtils.randomAToB(-.5, .5) * this.height;\n        this.vector.z = this.z + Proton.MathUtils.randomAToB(-.5, .5) * this.depth;\n        return this.vector;\n    }\n\n    BoxZone.prototype._dead = function(particle) {\n        if (particle.p.x + particle.radius < this.x - this.width / 2)\n            particle.dead = true;\n        else if (particle.p.x - particle.radius > this.x + this.width / 2)\n            particle.dead = true;\n\n        if (particle.p.y + particle.radius < this.y - this.height / 2)\n            particle.dead = true;\n        else if (particle.p.y - particle.radius > this.y + this.height / 2)\n            particle.dead = true;\n\n        if (particle.p.z + particle.radius < this.z - this.depth / 2)\n            particle.dead = true;\n        else if (particle.p.z - particle.radius > this.z + this.depth / 2)\n            particle.dead = true;\n    }\n\n    BoxZone.prototype._bound = function(particle) {\n        if (particle.p.x - particle.radius < this.x - this.width / 2) {\n            particle.p.x = this.x - this.width / 2 + particle.radius;\n            particle.v.x *= -this.friction;\n            this._static(particle, \"x\");\n        } else if (particle.p.x + particle.radius > this.x + this.width / 2) {\n            particle.p.x = this.x + this.width / 2 - particle.radius;\n            particle.v.x *= -this.friction;\n            this._static(particle, \"x\");\n        }\n\n        if (particle.p.y - particle.radius < this.y - this.height / 2) {\n            particle.p.y = this.y - this.height / 2 + particle.radius;\n            particle.v.y *= -this.friction;\n            this._static(particle, \"y\");\n        } else if (particle.p.y + particle.radius > this.y + this.height / 2) {\n            particle.p.y = this.y + this.height / 2 - particle.radius;\n            particle.v.y *= -this.friction;\n            this._static(particle, \"y\");\n        }\n\n        if (particle.p.z - particle.radius < this.z - this.depth / 2) {\n            particle.p.z = this.z - this.depth / 2 + particle.radius;\n            particle.v.z *= -this.friction;\n            this._static(particle, \"z\");\n        } else if (particle.p.z + particle.radius > this.z + this.depth / 2) {\n            particle.p.z = this.z + this.depth / 2 - particle.radius;\n            particle.v.z *= -this.friction;\n            this._static(particle, \"z\");\n        }\n    }\n\n    BoxZone.prototype._static = function(particle, axis) {\n        if (particle.v[axis] * particle.a[axis] > 0) return;\n        if (Math.abs(particle.v[axis]) < Math.abs(particle.a[axis]) * 0.0167 * this.max) {\n            particle.v[axis] = 0;\n            particle.a[axis] = 0;\n        }\n    }\n\n    BoxZone.prototype._cross = function(particle) {\n        if (particle.p.x + particle.radius < this.x - this.width / 2 && particle.v.x <= 0)\n            particle.p.x = this.x + this.width / 2 + particle.radius;\n        else if (particle.p.x - particle.radius > this.x + this.width / 2 && particle.v.x >= 0)\n            particle.p.x = this.x - this.width / 2 - particle.radius;\n\n        if (particle.p.y + particle.radius < this.y - this.height / 2 && particle.v.y <= 0)\n            particle.p.y = this.y + this.height / 2 + particle.radius;\n        else if (particle.p.y - particle.radius > this.y + this.height / 2 && particle.v.y >= 0)\n            particle.p.y = this.y - this.height / 2 - particle.radius;\n\n        if (particle.p.z + particle.radius < this.z - this.depth / 2 && particle.v.z <= 0)\n            particle.p.z = this.z + this.depth / 2 + particle.radius;\n        else if (particle.p.z - particle.radius > this.z + this.depth / 2 && particle.v.z >= 0)\n            particle.p.z = this.z - this.depth / 2 - particle.radius;\n    }\n\n    Proton.BoxZone = BoxZone;\n\n\n\n    /**\n     * ScreenZone is a 3d line zone\n     * @param {Number|Vector3D} x1 - the line's start point of x value or a Vector3D Object\n     * @param {Number|Vector3D} y1 - the line's start point of y value or a Vector3D Object\n     * @param {Number} z1 - the line's start point of z value \n     * @param {Number} x2 - the line's end point of x value \n     * @param {Number} y2 - the line's end point of y value \n     * @param {Number} z2 - the line's end point of z value \n     * @example \n     * var lineZone = new Proton.ScreenZone(0,0,0,100,100,0);\n     * or\n     * var lineZone = new Proton.ScreenZone(new Proton.Vector3D(0,0,0),new Proton.Vector3D(100,100,0));\n     * @extends {Zone}\n     * @constructor\n     */\n    function ScreenZone(camera, renderer, dis, dir) {\n        ScreenZone._super_.call(this);\n\n        this.camera = camera;\n        this.renderer = renderer;\n        this.dis = dis || 20;\n        dir = dir || \"1234\";\n        for (var i = 1; i < 5; i++)\n            this[\"d\" + i] = dir.indexOf(i + \"\") >= 0;\n\n        this.name = \"ScreenZone\";\n    }\n\n\n    Proton.Util.inherits(ScreenZone, Proton.Zone);\n    ScreenZone.prototype.getPosition = function() {\n        var vec2 = new Proton.Vector3D,\n            canvas;\n\n        return function() {\n            canvas = this.renderer.domElement;\n            vec2.x = Math.random() * canvas.width;\n            vec2.y = Math.random() * canvas.height;\n            this.vector.copy(Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas));\n            return this.vector;\n        }\n    }();\n\n    ScreenZone.prototype._dead = function(particle) {\n        var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n        var canvas = this.renderer.domElement;\n\n        if ((pos.y + particle.radius < -this.dis) && this.d1) {\n            particle.dead = true;\n        } else if ((pos.y - particle.radius > canvas.height + this.dis) && this.d3) {\n            particle.dead = true;\n        }\n\n        if ((pos.x + particle.radius < -this.dis) && this.d4) {\n            particle.dead = true;\n        } else if ((pos.x - particle.radius > canvas.width + this.dis) && this.d2) {\n            particle.dead = true;\n        }\n    }\n\n    ScreenZone.prototype._cross = function() {\n        var vec2 = new Proton.Vector3D;\n        return function(particle) {\n            var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n            var canvas = this.renderer.domElement;\n\n            if (pos.y + particle.radius < -this.dis) {\n                vec2.x = pos.x;\n                vec2.y = canvas.height + this.dis + particle.radius;\n                particle.p.y = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).y;\n            } else if (pos.y - particle.radius > canvas.height + this.dis) {\n                vec2.x = pos.x;\n                vec2.y = -this.dis - particle.radius;\n                particle.p.y = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).y;\n            }\n\n            if (pos.x + particle.radius < -this.dis) {\n                vec2.y = pos.y;\n                vec2.x = canvas.width + this.dis + particle.radius;\n                particle.p.x = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).x;\n            } else if (pos.x - particle.radius > canvas.width + this.dis) {\n                vec2.y = pos.y;\n                vec2.x = -this.dis - particle.radius;\n                particle.p.x = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).x;\n            }\n        }\n    }();\n\n    ScreenZone.prototype._bound = function(particle) {\n        var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n        var canvas = this.renderer.domElement;\n\n        if (pos.y + particle.radius < -this.dis) {\n            particle.v.y *= -1;\n        } else if (pos.y - particle.radius > canvas.height + this.dis) {\n            particle.v.y *= -1;\n        }\n\n        if (pos.x + particle.radius < -this.dis) {\n            particle.v.y *= -1;\n        } else if (pos.x - particle.radius > canvas.width + this.dis) {\n            particle.v.y *= -1;\n        }\n    }\n\n    Proton.ScreenZone = ScreenZone;\n\n\n/**\n * You can use this emit particles.\n *\n * This method will console.log the fixed number of your info  in updata or requestAnimationFrame\n * \n * use like this Proton.log('+12',mc); log 12 times\n *\n * @class Proton.log\n * @constructor\n * @param {*} logInfo;\n */\n\n    var log = function() {\n        if (window.console && window.console.trace) {\n            var arg = Array.prototype.slice.call(arguments);\n            var s1 = arguments[0] + \"\";\n            if (s1.indexOf('+') == 0) {\n                var n = parseInt(arguments[0]);\n                if (log.once < n) {\n                    arg.shift();\n                    console.trace.apply(console, arg);\n                    log.once++;\n                }\n            } else {\n                arg.unshift(\"+15\");\n                log.apply(console, arg);\n            }\n        }\n    }\n\n    log.once = 0;\n    Proton.log = log;\n\n\n\n    var Debug = Debug || {\n        addEventListener: function(proton, fun) {\n            proton.addEventListener(\"PROTON_UPDATE\", function(e) {\n                fun(e);\n            });\n        },\n\n        drawZone: function(proton, container, zone) {\n            var geometry, material, mesh;\n\n            if (zone instanceof Proton.PointZone) {\n                geometry = new THREE.SphereGeometry(15);\n            } else if (zone instanceof Proton.LineZone) {\n\n            } else if (zone instanceof Proton.BoxZone) {\n                geometry = new THREE.BoxGeometry(zone.width, zone.height, zone.depth);\n            } else if (zone instanceof Proton.SphereZone) {\n                geometry = new THREE.SphereGeometry(zone.radius, 10, 10);\n            } else if (zone instanceof Proton.MeshZone) {\n                if (zone.geometry instanceof THREE.Geometry)\n                    geometry = zone.geometry;\n                else\n                    geometry = zone.geometry.geometry;\n\n                geometry = new THREE.SphereGeometry(zone.radius, 10, 10);\n            }\n\n            material = new THREE.MeshBasicMaterial({ color: \"#2194ce\", wireframe: true });\n            mesh = new THREE.Mesh(geometry, material);\n            container.add(mesh);\n\n            this.addEventListener(proton, function(e) {\n                mesh.position.set(zone.x, zone.y, zone.z);\n            });\n        },\n\n        drawEmitter: function(proton, container, emitter, color) {\n            var geometry = new THREE.OctahedronGeometry(15);\n            var material = new THREE.MeshBasicMaterial({ color: color || \"#aaa\", wireframe: true });\n            var mesh = new THREE.Mesh(geometry, material);\n            container.add(mesh);\n\n            this.addEventListener(proton, function() {\n                mesh.position.copy(emitter.p);\n                mesh.rotation.set(emitter.rotation.x, emitter.rotation.y, emitter.rotation.z);\n            });\n        },\n\n        renderInfo: function() {\n            function getCreatedNumber(proton, type) {\n                var pool = type == \"material\" ? \"_materialPool\" : \"_targetPool\";\n                var renderer = proton.renderers[0];\n                return renderer[pool].cID;\n            }\n\n            function getEmitterPos(proton) {\n                var e = proton.emitters[0];\n                return Math.round(e.p.x) + \",\" + Math.round(e.p.y) + \",\" + Math.round(e.p.z);\n            }\n\n            return function(proton, style) {\n                this.addInfo(style);\n                var str = \"\";\n                switch (this._infoType) {\n                    case 2:\n                        str += \"emitter:\" + proton.emitters.length + \"<br>\";\n                        str += \"em speed:\" + proton.emitters[0].cID + \"<br>\";\n                        str += \"pos:\" + getEmitterPos(proton);\n                        break;\n\n                    case 3:\n                        str += proton.renderers[0].name + \"<br>\";\n                        str += \"target:\" + getCreatedNumber(proton, \"target\") + \"<br>\";\n                        str += \"material:\" + getCreatedNumber(proton, \"material\");\n                        break;\n\n                    default:\n                        str += \"particles:\" + proton.getCount() + \"<br>\";\n                        str += \"pool:\" + proton.pool.getCount() + \"<br>\";\n                        str += \"total:\" + (proton.getCount() + proton.pool.getCount());\n                }\n                this._infoCon.innerHTML = str;\n            }\n        }(),\n\n        addInfo: function() {\n            return function(style) {\n                var self = this;\n                if (!this._infoCon) {\n                    this._infoCon = document.createElement('div');\n                    this._infoCon.style.cssText = [\n                        'position:fixed;bottom:0px;left:0;cursor:pointer;',\n                        'opacity:0.9;z-index:10000;padding:10px;font-size:12px;',\n                        'width:120px;height:50px;background-color:#002;color:#0ff;'\n                    ].join('');\n\n                    this._infoType = 1;\n                    this._infoCon.addEventListener('click', function(event) {\n                        self._infoType++;\n                        if (self._infoType > 3) self._infoType = 1;\n                    }, false);\n\n                    var bg, color;\n                    switch (style) {\n                        case 2:\n                            bg = \"#201\";\n                            color = \"#f08\";\n                            break;\n\n                        case 3:\n                            bg = \"#020\";\n                            color = \"#0f0\";\n                            break;\n\n                        default:\n                            bg = \"#002\";\n                            color = \"#0ff\";\n                    }\n\n                    this._infoCon.style[\"background-color\"] = bg;\n                    this._infoCon.style[\"color\"] = color;\n                }\n\n                if (!this._infoCon.parentNode) document.body.appendChild(this._infoCon);\n            }\n        }()\n    }\n\n    Proton.Debug = Debug;\n\n    return Proton;\n}));"
  },
  {
    "path": "example/assets/suzanne.js",
    "content": "{\n\n    \"metadata\": { \"formatVersion\" : 3 },\n\n    \"materials\": [\t{\n\t\"DbgColor\" : 15658734,\n\t\"DbgIndex\" : 0,\n\t\"DbgName\" : \"default\",\n\t\"vertexColors\" : false\n\t}],\n\n    \"vertices\": [0.437500,0.765625,-0.164063,-0.437500,0.765625,-0.164063,0.500000,0.687500,-0.093750,-0.500000,0.687500,-0.093750,0.546875,0.578125,-0.054688,-0.546875,0.578125,-0.054688,0.351562,0.617188,0.023437,-0.351562,0.617188,0.023437,0.351562,0.718750,-0.031250,-0.351562,0.718750,-0.031250,0.351562,0.781250,-0.132813,-0.351562,0.781250,-0.132813,0.273438,0.796875,-0.164063,-0.273438,0.796875,-0.164063,0.203125,0.742188,-0.093750,-0.203125,0.742188,-0.093750,0.156250,0.648438,-0.054688,-0.156250,0.648438,-0.054688,0.078125,0.656250,-0.242188,-0.078125,0.656250,-0.242188,0.140625,0.742188,-0.242188,-0.140625,0.742188,-0.242188,0.242188,0.796875,-0.242188,-0.242188,0.796875,-0.242188,0.273438,0.796875,-0.328125,-0.273438,0.796875,-0.328125,0.203125,0.742188,-0.390625,-0.203125,0.742188,-0.390625,0.156250,0.648438,-0.437500,-0.156250,0.648438,-0.437500,0.351562,0.617188,-0.515625,-0.351562,0.617188,-0.515625,0.351562,0.718750,-0.453125,-0.351562,0.718750,-0.453125,0.351562,0.781250,-0.359375,-0.351562,0.781250,-0.359375,0.437500,0.765625,-0.328125,-0.437500,0.765625,-0.328125,0.500000,0.687500,-0.390625,-0.500000,0.687500,-0.390625,0.546875,0.578125,-0.437500,-0.546875,0.578125,-0.437500,0.625000,0.562500,-0.242188,-0.625000,0.562500,-0.242188,0.562500,0.671875,-0.242188,-0.562500,0.671875,-0.242188,0.468750,0.757812,-0.242188,-0.468750,0.757812,-0.242188,0.476562,0.773438,-0.242188,-0.476562,0.773438,-0.242188,0.445312,0.781250,-0.335938,-0.445312,0.781250,-0.335938,0.351562,0.804688,-0.375000,-0.351562,0.804688,-0.375000,0.265625,0.820312,-0.335938,-0.265625,0.820312,-0.335938,0.226562,0.820312,-0.242188,-0.226562,0.820312,-0.242188,0.265625,0.820312,-0.156250,-0.265625,0.820312,-0.156250,0.351562,0.828125,-0.242188,-0.351562,0.828125,-0.242188,0.351562,0.804688,-0.117188,-0.351562,0.804688,-0.117188,0.445312,0.781250,-0.156250,-0.445312,0.781250,-0.156250,0.000000,0.742188,-0.429688,0.000000,0.820312,-0.351563,0.000000,0.734375,0.679687,0.000000,0.781250,0.320312,0.000000,0.796875,0.187500,0.000000,0.718750,0.773437,0.000000,0.601562,-0.406250,0.000000,0.570312,-0.570312,0.000000,-0.546875,-0.898438,0.000000,-0.851562,-0.562500,0.000000,-0.828125,-0.070312,0.000000,-0.351562,0.382813,0.203125,0.562500,0.187500,-0.203125,0.562500,0.187500,0.312500,0.570312,0.437500,-0.312500,0.570312,0.437500,0.351562,0.570313,0.695312,-0.351562,0.570313,0.695312,0.367188,0.531250,0.890625,-0.367188,0.531250,0.890625,0.328125,0.523438,0.945312,-0.328125,0.523438,0.945312,0.179688,0.554688,0.968750,-0.179688,0.554688,0.968750,0.000000,0.578125,0.984375,0.437500,0.531250,0.140625,-0.437500,0.531250,0.140625,0.632812,0.539062,0.039062,-0.632812,0.539062,0.039062,0.828125,0.445312,-0.148438,-0.828125,0.445312,-0.148438,0.859375,0.593750,-0.429688,-0.859375,0.593750,-0.429688,0.710938,0.625000,-0.484375,-0.710938,0.625000,-0.484375,0.492188,0.687500,-0.601563,-0.492188,0.687500,-0.601563,0.320312,0.734375,-0.757813,-0.320312,0.734375,-0.757813,0.156250,0.757812,-0.718750,-0.156250,0.757812,-0.718750,0.062500,0.750000,-0.492188,-0.062500,0.750000,-0.492188,0.164062,0.773438,-0.414063,-0.164062,0.773438,-0.414063,0.125000,0.765625,-0.304688,-0.125000,0.765625,-0.304688,0.203125,0.742188,-0.093750,-0.203125,0.742188,-0.093750,0.375000,0.703125,-0.015625,-0.375000,0.703125,-0.015625,0.492188,0.671875,-0.062500,-0.492188,0.671875,-0.062500,0.625000,0.648438,-0.187500,-0.625000,0.648438,-0.187500,0.640625,0.648438,-0.296875,-0.640625,0.648438,-0.296875,0.601562,0.664062,-0.375000,-0.601562,0.664062,-0.375000,0.429688,0.718750,-0.437500,-0.429688,0.718750,-0.437500,0.250000,0.757812,-0.468750,-0.250000,0.757812,-0.468750,0.000000,0.734375,0.765625,0.109375,0.734375,0.718750,-0.109375,0.734375,0.718750,0.117188,0.710938,0.835937,-0.117188,0.710938,0.835937,0.062500,0.695313,0.882812,-0.062500,0.695313,0.882812,0.000000,0.687500,0.890625,0.000000,0.750000,0.195312,0.000000,0.742188,0.140625,0.101562,0.742188,0.148437,-0.101562,0.742188,0.148437,0.125000,0.750000,0.226562,-0.125000,0.750000,0.226562,0.085938,0.742188,0.289062,-0.085938,0.742188,0.289062,0.398438,0.671875,0.046875,-0.398438,0.671875,0.046875,0.617188,0.625000,-0.054688,-0.617188,0.625000,-0.054688,0.726562,0.601562,-0.203125,-0.726562,0.601562,-0.203125,0.742188,0.656250,-0.375000,-0.742188,0.656250,-0.375000,0.687500,0.726562,-0.414063,-0.687500,0.726562,-0.414063,0.437500,0.796875,-0.546875,-0.437500,0.796875,-0.546875,0.312500,0.835938,-0.640625,-0.312500,0.835938,-0.640625,0.203125,0.851562,-0.617188,-0.203125,0.851562,-0.617188,0.101562,0.843750,-0.429688,-0.101562,0.843750,-0.429688,0.125000,0.812500,0.101562,-0.125000,0.812500,0.101562,0.210938,0.710938,0.445312,-0.210938,0.710938,0.445312,0.250000,0.687500,0.703125,-0.250000,0.687500,0.703125,0.265625,0.664063,0.820312,-0.265625,0.664063,0.820312,0.234375,0.632813,0.914062,-0.234375,0.632813,0.914062,0.164062,0.632813,0.929688,-0.164062,0.632813,0.929688,0.000000,0.640625,0.945312,0.000000,0.726562,-0.046875,0.000000,0.765625,-0.210938,0.328125,0.742188,-0.476563,-0.328125,0.742188,-0.476563,0.164062,0.750000,-0.140625,-0.164062,0.750000,-0.140625,0.132812,0.757812,-0.210938,-0.132812,0.757812,-0.210938,0.117188,0.734375,0.687500,-0.117188,0.734375,0.687500,0.078125,0.750000,0.445312,-0.078125,0.750000,0.445312,0.000000,0.750000,0.445312,0.000000,0.742188,0.328125,0.093750,0.781250,0.273437,-0.093750,0.781250,0.273437,0.132812,0.796875,0.226562,-0.132812,0.796875,0.226562,0.109375,0.781250,0.132812,-0.109375,0.781250,0.132812,0.039062,0.781250,0.125000,-0.039062,0.781250,0.125000,0.000000,0.828125,0.203125,0.046875,0.812500,0.148437,-0.046875,0.812500,0.148437,0.093750,0.812500,0.156250,-0.093750,0.812500,0.156250,0.109375,0.828125,0.226562,-0.109375,0.828125,0.226562,0.078125,0.804688,0.250000,-0.078125,0.804688,0.250000,0.000000,0.804688,0.289062,0.257812,0.554688,0.312500,-0.257812,0.554688,0.312500,0.164062,0.710938,0.242187,-0.164062,0.710938,0.242187,0.179688,0.710938,0.312500,-0.179688,0.710938,0.312500,0.234375,0.554688,0.250000,-0.234375,0.554688,0.250000,0.000000,0.687500,0.875000,0.046875,0.687500,0.867187,-0.046875,0.687500,0.867187,0.093750,0.710938,0.820312,-0.093750,0.710938,0.820312,0.093750,0.726563,0.742187,-0.093750,0.726563,0.742187,0.000000,0.656250,0.781250,0.093750,0.664063,0.750000,-0.093750,0.664063,0.750000,0.093750,0.640625,0.812500,-0.093750,0.640625,0.812500,0.046875,0.632813,0.851562,-0.046875,0.632813,0.851562,0.000000,0.632813,0.859375,0.171875,0.781250,-0.218750,-0.171875,0.781250,-0.218750,0.187500,0.773438,-0.156250,-0.187500,0.773438,-0.156250,0.335938,0.757812,-0.429688,-0.335938,0.757812,-0.429688,0.273438,0.773438,-0.421875,-0.273438,0.773438,-0.421875,0.421875,0.773438,-0.398438,-0.421875,0.773438,-0.398438,0.562500,0.695312,-0.351563,-0.562500,0.695312,-0.351563,0.585938,0.687500,-0.289063,-0.585938,0.687500,-0.289063,0.578125,0.679688,-0.195313,-0.578125,0.679688,-0.195313,0.476562,0.718750,-0.101563,-0.476562,0.718750,-0.101563,0.375000,0.742188,-0.062500,-0.375000,0.742188,-0.062500,0.226562,0.781250,-0.109375,-0.226562,0.781250,-0.109375,0.179688,0.781250,-0.296875,-0.179688,0.781250,-0.296875,0.210938,0.781250,-0.375000,-0.210938,0.781250,-0.375000,0.234375,0.757812,-0.359375,-0.234375,0.757812,-0.359375,0.195312,0.757812,-0.296875,-0.195312,0.757812,-0.296875,0.242188,0.757812,-0.125000,-0.242188,0.757812,-0.125000,0.375000,0.726562,-0.085938,-0.375000,0.726562,-0.085938,0.460938,0.703125,-0.117188,-0.460938,0.703125,-0.117188,0.546875,0.671875,-0.210938,-0.546875,0.671875,-0.210938,0.554688,0.671875,-0.281250,-0.554688,0.671875,-0.281250,0.531250,0.679688,-0.335938,-0.531250,0.679688,-0.335938,0.414062,0.750000,-0.390625,-0.414062,0.750000,-0.390625,0.281250,0.765625,-0.398438,-0.281250,0.765625,-0.398438,0.335938,0.750000,-0.406250,-0.335938,0.750000,-0.406250,0.203125,0.750000,-0.171875,-0.203125,0.750000,-0.171875,0.195312,0.750000,-0.226563,-0.195312,0.750000,-0.226563,0.109375,0.609375,-0.460938,-0.109375,0.609375,-0.460938,0.195312,0.617188,-0.664062,-0.195312,0.617188,-0.664062,0.335938,0.593750,-0.687500,-0.335938,0.593750,-0.687500,0.484375,0.554688,-0.554688,-0.484375,0.554688,-0.554688,0.679688,0.492187,-0.453125,-0.679688,0.492187,-0.453125,0.796875,0.460937,-0.406250,-0.796875,0.460937,-0.406250,0.773438,0.375000,-0.164063,-0.773438,0.375000,-0.164063,0.601562,0.414062,-0.000000,-0.601562,0.414062,-0.000000,0.437500,0.468750,0.093750,-0.437500,0.468750,0.093750,0.000000,0.289062,-0.898438,0.000000,-0.078125,-0.984375,0.000000,-0.671875,0.195313,0.000000,0.187500,0.460938,0.000000,0.460938,0.976562,0.000000,0.343750,0.804688,0.000000,0.320313,0.570312,0.000000,0.281250,0.484375,0.851562,0.054687,-0.234375,-0.851562,0.054687,-0.234375,0.859375,-0.046875,-0.320312,-0.859375,-0.046875,-0.320312,0.773438,-0.437500,-0.265625,-0.773438,-0.437500,-0.265625,0.460938,-0.703125,-0.437500,-0.460938,-0.703125,-0.437500,0.734375,0.070312,0.046875,-0.734375,0.070312,0.046875,0.593750,-0.164062,0.125000,-0.593750,-0.164062,0.125000,0.640625,-0.429688,0.007813,-0.640625,-0.429688,0.007813,0.335938,-0.664062,-0.054687,-0.335938,-0.664062,-0.054687,0.234375,0.406250,0.351562,-0.234375,0.406250,0.351562,0.179688,0.257813,0.414062,-0.179688,0.257813,0.414062,0.289062,0.382813,0.710938,-0.289062,0.382813,0.710938,0.250000,0.390625,0.500000,-0.250000,0.390625,0.500000,0.328125,0.398438,0.914062,-0.328125,0.398438,0.914062,0.140625,0.367188,0.757812,-0.140625,0.367188,0.757812,0.125000,0.359375,0.539062,-0.125000,0.359375,0.539062,0.164062,0.437500,0.945312,-0.164062,0.437500,0.945312,0.218750,0.429688,0.281250,-0.218750,0.429688,0.281250,0.210938,0.468750,0.226562,-0.210938,0.468750,0.226562,0.203125,0.500000,0.171875,-0.203125,0.500000,0.171875,0.210938,0.164063,0.390625,-0.210938,0.164063,0.390625,0.296875,-0.265625,0.312500,-0.296875,-0.265625,0.312500,0.343750,-0.539062,0.148438,-0.343750,-0.539062,0.148438,0.453125,-0.382813,-0.867188,-0.453125,-0.382813,-0.867188,0.453125,-0.070313,-0.929688,-0.453125,-0.070313,-0.929688,0.453125,0.234375,-0.851562,-0.453125,0.234375,-0.851562,0.460938,0.429687,-0.523438,-0.460938,0.429687,-0.523438,0.726562,0.335937,-0.406250,-0.726562,0.335937,-0.406250,0.632812,0.281250,-0.453125,-0.632812,0.281250,-0.453125,0.640625,0.054687,-0.703125,-0.640625,0.054687,-0.703125,0.796875,0.125000,-0.562500,-0.796875,0.125000,-0.562500,0.796875,-0.117188,-0.617188,-0.796875,-0.117188,-0.617188,0.640625,-0.195313,-0.750000,-0.640625,-0.195313,-0.750000,0.640625,-0.445313,-0.679688,-0.640625,-0.445313,-0.679688,0.796875,-0.359375,-0.539062,-0.796875,-0.359375,-0.539062,0.617188,-0.585938,-0.328125,-0.617188,-0.585938,-0.328125,0.484375,-0.546875,-0.023437,-0.484375,-0.546875,-0.023437,0.820312,-0.203125,-0.328125,-0.820312,-0.203125,-0.328125,0.406250,0.148438,0.171875,-0.406250,0.148438,0.171875,0.429688,-0.210937,0.195313,-0.429688,-0.210937,0.195313,0.890625,-0.234375,-0.406250,-0.890625,-0.234375,-0.406250,0.773438,-0.125000,0.140625,-0.773438,-0.125000,0.140625,1.039062,-0.328125,0.101563,-1.039062,-0.328125,0.101563,1.281250,-0.429688,-0.054687,-1.281250,-0.429688,-0.054687,1.351562,-0.421875,-0.320312,-1.351562,-0.421875,-0.320312,1.234375,-0.421875,-0.507812,-1.234375,-0.421875,-0.507812,1.023438,-0.312500,-0.476562,-1.023438,-0.312500,-0.476562,1.015625,-0.289063,-0.414062,-1.015625,-0.289063,-0.414062,1.187500,-0.390625,-0.437500,-1.187500,-0.390625,-0.437500,1.265625,-0.406250,-0.289062,-1.265625,-0.406250,-0.289062,1.210938,-0.406250,-0.078125,-1.210938,-0.406250,-0.078125,1.031250,-0.304688,0.039063,-1.031250,-0.304688,0.039063,0.828125,-0.132812,0.070313,-0.828125,-0.132812,0.070313,0.921875,-0.218750,-0.359375,-0.921875,-0.218750,-0.359375,0.945312,-0.289062,-0.304688,-0.945312,-0.289062,-0.304688,0.882812,-0.210938,0.023438,-0.882812,-0.210938,0.023438,1.039062,-0.367188,0.000000,-1.039062,-0.367188,0.000000,1.187500,-0.445312,-0.093750,-1.187500,-0.445312,-0.093750,1.234375,-0.445312,-0.250000,-1.234375,-0.445312,-0.250000,1.171875,-0.437500,-0.359375,-1.171875,-0.437500,-0.359375,1.023438,-0.359375,-0.343750,-1.023438,-0.359375,-0.343750,0.843750,-0.210938,-0.289062,-0.843750,-0.210938,-0.289062,0.835938,-0.273438,-0.171875,-0.835938,-0.273438,-0.171875,0.757812,-0.273438,-0.093750,-0.757812,-0.273438,-0.093750,0.820312,-0.273438,-0.085937,-0.820312,-0.273438,-0.085937,0.843750,-0.273438,-0.015625,-0.843750,-0.273438,-0.015625,0.812500,-0.273438,0.015625,-0.812500,-0.273438,0.015625,0.726562,-0.070312,0.000000,-0.726562,-0.070312,0.000000,0.718750,-0.171875,0.023438,-0.718750,-0.171875,0.023438,0.718750,-0.187500,-0.039062,-0.718750,-0.187500,-0.039062,0.796875,-0.210938,-0.203125,-0.796875,-0.210938,-0.203125,0.890625,-0.265625,-0.242187,-0.890625,-0.265625,-0.242187,0.890625,-0.320312,-0.234375,-0.890625,-0.320312,-0.234375,0.812500,-0.320312,0.015625,-0.812500,-0.320312,0.015625,0.851562,-0.320312,-0.015625,-0.851562,-0.320312,-0.015625,0.828125,-0.320312,-0.078125,-0.828125,-0.320312,-0.078125,0.765625,-0.320312,-0.093750,-0.765625,-0.320312,-0.093750,0.843750,-0.320312,-0.171875,-0.843750,-0.320312,-0.171875,1.039062,-0.414062,-0.328125,-1.039062,-0.414062,-0.328125,1.187500,-0.484375,-0.343750,-1.187500,-0.484375,-0.343750,1.257812,-0.492188,-0.242187,-1.257812,-0.492188,-0.242187,1.210938,-0.484375,-0.085937,-1.210938,-0.484375,-0.085937,1.046875,-0.421875,0.000000,-1.046875,-0.421875,0.000000,0.882812,-0.265625,0.015625,-0.882812,-0.265625,0.015625,0.953125,-0.343750,-0.289062,-0.953125,-0.343750,-0.289062,0.890625,-0.328125,-0.109375,-0.890625,-0.328125,-0.109375,0.937500,-0.335938,-0.062500,-0.937500,-0.335938,-0.062500,1.000000,-0.367188,-0.125000,-1.000000,-0.367188,-0.125000,0.960938,-0.351562,-0.171875,-0.960938,-0.351562,-0.171875,1.015625,-0.375000,-0.234375,-1.015625,-0.375000,-0.234375,1.054688,-0.382812,-0.187500,-1.054688,-0.382812,-0.187500,1.109375,-0.390625,-0.210937,-1.109375,-0.390625,-0.210937,1.085938,-0.390625,-0.273437,-1.085938,-0.390625,-0.273437,1.023438,-0.484375,-0.437500,-1.023438,-0.484375,-0.437500,1.250000,-0.546875,-0.468750,-1.250000,-0.546875,-0.468750,1.367188,-0.500000,-0.296875,-1.367188,-0.500000,-0.296875,1.312500,-0.531250,-0.054687,-1.312500,-0.531250,-0.054687,1.039062,-0.492188,0.085938,-1.039062,-0.492188,0.085938,0.789062,-0.328125,0.125000,-0.789062,-0.328125,0.125000,0.859375,-0.382813,-0.382812,-0.859375,-0.382813,-0.382812],\n\n    \"morphTargets\": [],\n\n    \"normals\": [],\n\n    \"colors\": [],\n\n    \"uvs\": [[]],\n\n    \"faces\": [3,46,0,2,44,0,3,3,1,47,45,0,3,44,2,4,42,0,3,5,3,45,43,0,3,2,8,6,4,0,3,7,9,3,5,0,3,0,10,8,2,0,3,9,11,1,3,0,3,10,12,14,8,0,3,15,13,11,9,0,3,8,14,16,6,0,3,17,15,9,7,0,3,14,20,18,16,0,3,19,21,15,17,0,3,12,22,20,14,0,3,21,23,13,15,0,3,22,24,26,20,0,3,27,25,23,21,0,3,20,26,28,18,0,3,29,27,21,19,0,3,26,32,30,28,0,3,31,33,27,29,0,3,24,34,32,26,0,3,33,35,25,27,0,3,34,36,38,32,0,3,39,37,35,33,0,3,32,38,40,30,0,3,41,39,33,31,0,3,38,44,42,40,0,3,43,45,39,41,0,3,36,46,44,38,0,3,45,47,37,39,0,3,46,36,50,48,0,3,51,37,47,49,0,3,36,34,52,50,0,3,53,35,37,51,0,3,34,24,54,52,0,3,55,25,35,53,0,3,24,22,56,54,0,3,57,23,25,55,0,3,22,12,58,56,0,3,59,13,23,57,0,3,12,10,62,58,0,3,63,11,13,59,0,3,10,0,64,62,0,3,65,1,11,63,0,3,0,46,48,64,0,3,49,47,1,65,0,2,60,64,48,0,2,49,65,61,0,2,62,64,60,0,2,61,65,63,0,2,60,58,62,0,2,63,59,61,0,2,60,56,58,0,2,59,57,61,0,2,60,54,56,0,2,57,55,61,0,2,60,52,54,0,2,55,53,61,0,2,60,50,52,0,2,53,51,61,0,2,60,48,50,0,2,51,49,61,0,3,88,173,175,90,0,3,175,174,89,90,0,3,86,171,173,88,0,3,174,172,87,89,0,3,84,169,171,86,0,3,172,170,85,87,0,3,82,167,169,84,0,3,170,168,83,85,0,3,80,165,167,82,0,3,168,166,81,83,0,3,78,91,145,163,0,3,146,92,79,164,0,3,91,93,147,145,0,3,148,94,92,146,0,3,93,95,149,147,0,3,150,96,94,148,0,3,95,97,151,149,0,3,152,98,96,150,0,3,97,99,153,151,0,3,154,100,98,152,0,3,99,101,155,153,0,3,156,102,100,154,0,3,101,103,157,155,0,3,158,104,102,156,0,3,103,105,159,157,0,3,160,106,104,158,0,3,105,107,161,159,0,3,162,108,106,160,0,3,107,66,67,161,0,3,67,66,108,162,0,3,109,127,159,161,0,3,160,128,110,162,0,3,127,178,157,159,0,3,158,179,128,160,0,3,125,155,157,178,0,3,158,156,126,179,0,3,123,153,155,125,0,3,156,154,124,126,0,3,121,151,153,123,0,3,154,152,122,124,0,3,119,149,151,121,0,3,152,150,120,122,0,3,117,147,149,119,0,3,150,148,118,120,0,3,115,145,147,117,0,3,148,146,116,118,0,3,113,163,145,115,0,3,146,164,114,116,0,3,113,180,176,163,0,3,176,181,114,164,0,3,109,161,67,111,0,3,67,162,110,112,0,3,111,67,177,182,0,3,177,67,112,183,0,3,176,180,182,177,0,3,183,181,176,177,0,3,134,136,175,173,0,3,175,136,135,174,0,3,132,134,173,171,0,3,174,135,133,172,0,3,130,132,171,169,0,3,172,133,131,170,0,3,165,186,184,167,0,3,185,187,166,168,0,3,130,169,167,184,0,3,168,170,131,185,0,3,143,189,188,186,0,3,188,189,144,187,0,3,184,186,188,68,0,3,188,187,185,68,0,3,129,130,184,68,0,3,185,131,129,68,0,3,141,192,190,143,0,3,191,193,142,144,0,3,139,194,192,141,0,3,193,195,140,142,0,3,138,196,194,139,0,3,195,197,138,140,0,3,137,70,196,138,0,3,197,70,137,138,0,3,189,143,190,69,0,3,191,144,189,69,0,3,69,190,205,207,0,3,206,191,69,207,0,3,70,198,199,196,0,3,200,198,70,197,0,3,196,199,201,194,0,3,202,200,197,195,0,3,194,201,203,192,0,3,204,202,195,193,0,3,192,203,205,190,0,3,206,204,193,191,0,3,198,203,201,199,0,3,202,204,198,200,0,3,198,207,205,203,0,3,206,207,198,204,0,3,138,139,163,176,0,3,164,140,138,176,0,3,139,141,210,163,0,3,211,142,140,164,0,3,141,143,212,210,0,3,213,144,142,211,0,3,143,186,165,212,0,3,166,187,144,213,0,3,80,208,212,165,0,3,213,209,81,166,0,3,208,214,210,212,0,3,211,215,209,213,0,3,78,163,210,214,0,3,211,164,79,215,0,3,130,129,71,221,0,3,71,129,131,222,0,3,132,130,221,219,0,3,222,131,133,220,0,3,134,132,219,217,0,3,220,133,135,218,0,3,136,134,217,216,0,3,218,135,136,216,0,3,216,217,228,230,0,3,229,218,216,230,0,3,217,219,226,228,0,3,227,220,218,229,0,3,219,221,224,226,0,3,225,222,220,227,0,3,221,71,223,224,0,3,223,71,222,225,0,3,223,230,228,224,0,3,229,230,223,225,0,2,224,228,226,0,2,227,229,225,0,3,182,180,233,231,0,3,234,181,183,232,0,3,111,182,231,253,0,3,232,183,112,254,0,3,109,111,253,255,0,3,254,112,110,256,0,3,180,113,251,233,0,3,252,114,181,234,0,3,113,115,249,251,0,3,250,116,114,252,0,3,115,117,247,249,0,3,248,118,116,250,0,3,117,119,245,247,0,3,246,120,118,248,0,3,119,121,243,245,0,3,244,122,120,246,0,3,121,123,241,243,0,3,242,124,122,244,0,3,123,125,239,241,0,3,240,126,124,242,0,3,125,178,235,239,0,3,236,179,126,240,0,3,178,127,237,235,0,3,238,128,179,236,0,3,127,109,255,237,0,3,256,110,128,238,0,3,237,255,257,275,0,3,258,256,238,276,0,3,235,237,275,277,0,3,276,238,236,278,0,3,239,235,277,273,0,3,278,236,240,274,0,3,241,239,273,271,0,3,274,240,242,272,0,3,243,241,271,269,0,3,272,242,244,270,0,3,245,243,269,267,0,3,270,244,246,268,0,3,247,245,267,265,0,3,268,246,248,266,0,3,249,247,265,263,0,3,266,248,250,264,0,3,251,249,263,261,0,3,264,250,252,262,0,3,233,251,261,279,0,3,262,252,234,280,0,3,255,253,259,257,0,3,260,254,256,258,0,3,253,231,281,259,0,3,282,232,254,260,0,3,231,233,279,281,0,3,280,234,232,282,0,3,66,107,283,72,0,3,284,108,66,72,0,3,107,105,285,283,0,3,286,106,108,284,0,3,105,103,287,285,0,3,288,104,106,286,0,3,103,101,289,287,0,3,290,102,104,288,0,3,101,99,291,289,0,3,292,100,102,290,0,3,99,97,293,291,0,3,294,98,100,292,0,3,97,95,295,293,0,3,296,96,98,294,0,3,95,93,297,295,0,3,298,94,96,296,0,3,93,91,299,297,0,3,300,92,94,298,0,3,307,308,327,337,0,3,328,308,307,338,0,3,306,307,337,335,0,3,338,307,306,336,0,3,305,306,335,339,0,3,336,306,305,340,0,3,88,90,305,339,0,3,305,90,89,340,0,3,86,88,339,333,0,3,340,89,87,334,0,3,84,86,333,329,0,3,334,87,85,330,0,3,82,84,329,331,0,3,330,85,83,332,0,3,329,335,337,331,0,3,338,336,330,332,0,3,329,333,339,335,0,3,340,334,330,336,0,3,325,331,337,327,0,3,338,332,326,328,0,3,80,82,331,325,0,3,332,83,81,326,0,3,208,341,343,214,0,3,344,342,209,215,0,3,80,325,341,208,0,3,342,326,81,209,0,3,78,214,343,345,0,3,344,215,79,346,0,3,78,345,299,91,0,3,300,346,79,92,0,3,76,323,351,303,0,3,352,324,76,303,0,3,303,351,349,77,0,3,350,352,303,77,0,3,77,349,347,304,0,3,348,350,77,304,0,3,304,347,327,308,0,3,328,348,304,308,0,3,325,327,347,341,0,3,348,328,326,342,0,3,295,297,317,309,0,3,318,298,296,310,0,3,75,315,323,76,0,3,324,316,75,76,0,3,301,357,355,302,0,3,356,358,301,302,0,3,302,355,353,74,0,3,354,356,302,74,0,3,74,353,315,75,0,3,316,354,74,75,0,3,291,293,361,363,0,3,362,294,292,364,0,3,363,361,367,365,0,3,368,362,364,366,0,3,365,367,369,371,0,3,370,368,366,372,0,3,371,369,375,373,0,3,376,370,372,374,0,3,313,377,373,375,0,3,374,378,314,376,0,3,315,353,373,377,0,3,374,354,316,378,0,3,353,355,371,373,0,3,372,356,354,374,0,3,355,357,365,371,0,3,366,358,356,372,0,3,357,359,363,365,0,3,364,360,358,366,0,3,289,291,363,359,0,3,364,292,290,360,0,3,73,359,357,301,0,3,358,360,73,301,0,3,283,285,287,289,0,3,288,286,284,290,0,3,283,289,359,73,0,3,360,290,284,73,0,2,72,283,73,0,2,73,284,72,0,3,293,295,309,361,0,3,310,296,294,362,0,3,309,311,367,361,0,3,368,312,310,362,0,3,311,381,369,367,0,3,370,382,312,368,0,3,313,375,369,381,0,3,370,376,314,382,0,3,347,349,385,383,0,3,386,350,348,384,0,3,317,383,385,319,0,3,386,384,318,320,0,3,297,299,383,317,0,3,384,300,298,318,0,3,299,343,341,383,0,3,342,344,300,384,0,2,341,347,383,0,2,384,348,342,0,2,299,345,343,0,2,344,346,300,0,3,313,321,379,377,0,3,380,322,314,378,0,3,315,377,379,323,0,3,380,378,316,324,0,3,319,385,379,321,0,3,380,386,320,322,0,3,349,351,379,385,0,3,380,352,350,386,0,2,323,379,351,0,2,352,380,324,0,3,399,387,413,401,0,3,414,388,400,402,0,3,399,401,403,397,0,3,404,402,400,398,0,3,397,403,405,395,0,3,406,404,398,396,0,3,395,405,407,393,0,3,408,406,396,394,0,3,393,407,409,391,0,3,410,408,394,392,0,3,391,409,411,389,0,3,412,410,392,390,0,3,409,419,417,411,0,3,418,420,410,412,0,3,407,421,419,409,0,3,420,422,408,410,0,3,405,423,421,407,0,3,422,424,406,408,0,3,403,425,423,405,0,3,424,426,404,406,0,3,401,427,425,403,0,3,426,428,402,404,0,3,401,413,415,427,0,3,416,414,402,428,0,3,317,319,443,441,0,3,444,320,318,442,0,3,319,389,411,443,0,3,412,390,320,444,0,3,309,317,441,311,0,3,442,318,310,312,0,3,381,429,413,387,0,3,414,430,382,388,0,3,411,417,439,443,0,3,440,418,412,444,0,3,437,445,443,439,0,3,444,446,438,440,0,3,433,445,437,435,0,3,438,446,434,436,0,3,431,447,445,433,0,3,446,448,432,434,0,3,429,447,431,449,0,3,432,448,430,450,0,3,413,429,449,415,0,3,450,430,414,416,0,3,311,447,429,381,0,3,430,448,312,382,0,3,311,441,445,447,0,3,446,442,312,448,0,2,441,443,445,0,2,446,444,442,0,3,415,449,451,475,0,3,452,450,416,476,0,3,449,431,461,451,0,3,462,432,450,452,0,3,431,433,459,461,0,3,460,434,432,462,0,3,433,435,457,459,0,3,458,436,434,460,0,3,435,437,455,457,0,3,456,438,436,458,0,3,437,439,453,455,0,3,454,440,438,456,0,3,439,417,473,453,0,3,474,418,440,454,0,3,427,415,475,463,0,3,476,416,428,464,0,3,425,427,463,465,0,3,464,428,426,466,0,3,423,425,465,467,0,3,466,426,424,468,0,3,421,423,467,469,0,3,468,424,422,470,0,3,419,421,469,471,0,3,470,422,420,472,0,3,417,419,471,473,0,3,472,420,418,474,0,3,457,455,479,477,0,3,480,456,458,478,0,3,477,479,481,483,0,3,482,480,478,484,0,3,483,481,487,485,0,3,488,482,484,486,0,3,485,487,489,491,0,3,490,488,486,492,0,3,463,475,485,491,0,3,486,476,464,492,0,3,451,483,485,475,0,3,486,484,452,476,0,3,451,461,477,483,0,3,478,462,452,484,0,3,457,477,461,459,0,3,462,478,458,460,0,3,453,473,479,455,0,3,480,474,454,456,0,3,471,481,479,473,0,3,480,482,472,474,0,3,469,487,481,471,0,3,482,488,470,472,0,3,467,489,487,469,0,3,488,490,468,470,0,3,465,491,489,467,0,3,490,492,466,468,0,2,463,491,465,0,2,466,492,464,0,3,391,389,503,501,0,3,504,390,392,502,0,3,393,391,501,499,0,3,502,392,394,500,0,3,395,393,499,497,0,3,500,394,396,498,0,3,397,395,497,495,0,3,498,396,398,496,0,3,399,397,495,493,0,3,496,398,400,494,0,3,387,399,493,505,0,3,494,400,388,506,0,3,493,501,503,505,0,3,504,502,494,506,0,3,493,495,499,501,0,3,500,496,494,502,0,2,495,497,499,0,2,500,498,496,0,3,313,381,387,505,0,3,388,382,314,506,0,3,313,505,503,321,0,3,504,506,314,322,0,3,319,321,503,389,0,3,504,322,320,390,0]\n\n}"
  },
  {
    "path": "example/assets/teapot.json",
    "content": "{\"metadata\":{\"version\":4.3,\"type\":\"Object\",\"generator\":\"ObjectExporter\"},\"geometries\":[{\"uuid\":\"15930b1c-1b50-4926-a0ac-df433b9c4f96\",\"type\":\"Geometry\",\"data\":{\"vertices\":[0.699999988079071,1.2000000476837158,0,0.6456999778747559,1.2000000476837158,0.27469998598098755,0.6366999745368958,1.236899971961975,0.27090001106262207,0.6901999711990356,1.236899971961975,0,0.6471999883651733,1.2491999864578247,0.2754000127315521,0.7016000151634216,1.2491999864578247,0,0.6685000061988831,1.236899971961975,0.28439998626708984,0.7246000170707703,1.236899971961975,0,0.6919000148773193,1.2000000476837158,0.29440000653266907,0.75,1.2000000476837158,0,0.4970000088214874,1.2000000476837158,0.4970000088214874,0.4900999963283539,1.236899971961975,0.4900999963283539,0.49810001254081726,1.2491999864578247,0.49810001254081726,0.5145000219345093,1.236899971961975,0.5145000219345093,0.5325000286102295,1.2000000476837158,0.5325000286102295,0.27469998598098755,1.2000000476837158,0.6456999778747559,0.27090001106262207,1.236899971961975,0.6366999745368958,0.2754000127315521,1.2491999864578247,0.6471999883651733,0.28439998626708984,1.236899971961975,0.6685000061988831,0.29440000653266907,1.2000000476837158,0.6919000148773193,0,1.2000000476837158,0.699999988079071,0,1.236899971961975,0.6901999711990356,0,1.2491999864578247,0.7016000151634216,0,1.236899971961975,0.7246000170707703,0,1.2000000476837158,0.75,-0.2937000095844269,1.2000000476837158,0.6456999778747559,-0.27889999747276306,1.236899971961975,0.6366999745368958,-0.2777000069618225,1.2491999864578247,0.6471999883651733,-0.2847000062465668,1.236899971961975,0.6685000061988831,-0.29440000653266907,1.2000000476837158,0.6919000148773193,-0.5138999819755554,1.2000000476837158,0.4970000088214874,-0.49720001220703125,1.236899971961975,0.4900999963283539,-0.5001999735832214,1.2491999864578247,0.49810001254081726,-0.5146999955177307,1.236899971961975,0.5145000219345093,-0.5325000286102295,1.2000000476837158,0.5325000286102295,-0.6521000266075134,1.2000000476837158,0.27469998598098755,-0.6394000053405762,1.236899971961975,0.27090001106262207,-0.6480000019073486,1.2491999864578247,0.2754000127315521,-0.6686000227928162,1.236899971961975,0.28439998626708984,-0.6919000148773193,1.2000000476837158,0.29440000653266907,-0.699999988079071,1.2000000476837158,0,-0.6901999711990356,1.236899971961975,0,-0.7016000151634216,1.2491999864578247,0,-0.7246000170707703,1.236899971961975,0,-0.75,1.2000000476837158,0,-0.6456999778747559,1.2000000476837158,-0.27469998598098755,-0.6366999745368958,1.236899971961975,-0.27090001106262207,-0.6471999883651733,1.2491999864578247,-0.2754000127315521,-0.6685000061988831,1.236899971961975,-0.28439998626708984,-0.6919000148773193,1.2000000476837158,-0.29440000653266907,-0.4970000088214874,1.2000000476837158,-0.4970000088214874,-0.4900999963283539,1.236899971961975,-0.4900999963283539,-0.49810001254081726,1.2491999864578247,-0.49810001254081726,-0.5145000219345093,1.236899971961975,-0.5145000219345093,-0.5325000286102295,1.2000000476837158,-0.5325000286102295,-0.27469998598098755,1.2000000476837158,-0.6456999778747559,-0.27090001106262207,1.236899971961975,-0.6366999745368958,-0.2754000127315521,1.2491999864578247,-0.6471999883651733,-0.28439998626708984,1.236899971961975,-0.6685000061988831,-0.29440000653266907,1.2000000476837158,-0.6919000148773193,0,1.2000000476837158,-0.699999988079071,0,1.236899971961975,-0.6901999711990356,0,1.2491999864578247,-0.7016000151634216,0,1.236899971961975,-0.7246000170707703,0,1.2000000476837158,-0.75,0.27469998598098755,1.2000000476837158,-0.6456999778747559,0.27090001106262207,1.236899971961975,-0.6366999745368958,0.2754000127315521,1.2491999864578247,-0.6471999883651733,0.28439998626708984,1.236899971961975,-0.6685000061988831,0.29440000653266907,1.2000000476837158,-0.6919000148773193,0.4970000088214874,1.2000000476837158,-0.4970000088214874,0.4900999963283539,1.236899971961975,-0.4900999963283539,0.49810001254081726,1.2491999864578247,-0.49810001254081726,0.5145000219345093,1.236899971961975,-0.5145000219345093,0.5325000286102295,1.2000000476837158,-0.5325000286102295,0.6456999778747559,1.2000000476837158,-0.27469998598098755,0.6366999745368958,1.236899971961975,-0.27090001106262207,0.6471999883651733,1.2491999864578247,-0.2754000127315521,0.6685000061988831,1.236899971961975,-0.28439998626708984,0.6919000148773193,1.2000000476837158,-0.29440000653266907,0.7766000032424927,1.0037000179290771,0.3303999900817871,0.8417999744415283,1.0037000179290771,0,0.8503999710083008,0.8108999729156494,0.3617999851703644,0.9218999743461609,0.8108999729156494,0,0.9027000069618225,0.6251999735832214,0.3840999901294708,0.9785000085830688,0.6251999735832214,0,0.9225000143051147,0.44999998807907104,0.39250001311302185,1,0.44999998807907104,0,0.5976999998092651,1.0037000179290771,0.5976999998092651,0.6545000076293945,0.8108999729156494,0.6545000076293945,0.6947000026702881,0.6251999735832214,0.6947000026702881,0.7099999785423279,0.44999998807907104,0.7099999785423279,0.3303999900817871,1.0037000179290771,0.7766000032424927,0.3617999851703644,0.8108999729156494,0.8503999710083008,0.3840999901294708,0.6251999735832214,0.9027000069618225,0.39250001311302185,0.44999998807907104,0.9225000143051147,0,1.0037000179290771,0.8417999744415283,0,0.8108999729156494,0.9218999743461609,0,0.6251999735832214,0.9785000085830688,0,0.44999998807907104,1,-0.3303999900817871,1.0037000179290771,0.7766000032424927,-0.3617999851703644,0.8108999729156494,0.8503999710083008,-0.3840999901294708,0.6251999735832214,0.9027000069618225,-0.39250001311302185,0.44999998807907104,0.9225000143051147,-0.5976999998092651,1.0037000179290771,0.5976999998092651,-0.6545000076293945,0.8108999729156494,0.6545000076293945,-0.6947000026702881,0.6251999735832214,0.6947000026702881,-0.7099999785423279,0.44999998807907104,0.7099999785423279,-0.7766000032424927,1.0037000179290771,0.3303999900817871,-0.8503999710083008,0.8108999729156494,0.3617999851703644,-0.9027000069618225,0.6251999735832214,0.3840999901294708,-0.9225000143051147,0.44999998807907104,0.39250001311302185,-0.8417999744415283,1.0037000179290771,0,-0.9218999743461609,0.8108999729156494,0,-0.9785000085830688,0.6251999735832214,0,-1,0.44999998807907104,0,-0.7766000032424927,1.0037000179290771,-0.3303999900817871,-0.8503999710083008,0.8108999729156494,-0.3617999851703644,-0.9027000069618225,0.6251999735832214,-0.3840999901294708,-0.9225000143051147,0.44999998807907104,-0.39250001311302185,-0.5976999998092651,1.0037000179290771,-0.5976999998092651,-0.6545000076293945,0.8108999729156494,-0.6545000076293945,-0.6947000026702881,0.6251999735832214,-0.6947000026702881,-0.7099999785423279,0.44999998807907104,-0.7099999785423279,-0.3303999900817871,1.0037000179290771,-0.7766000032424927,-0.3617999851703644,0.8108999729156494,-0.8503999710083008,-0.3840999901294708,0.6251999735832214,-0.9027000069618225,-0.39250001311302185,0.44999998807907104,-0.9225000143051147,0,1.0037000179290771,-0.8417999744415283,0,0.8108999729156494,-0.9218999743461609,0,0.6251999735832214,-0.9785000085830688,0,0.44999998807907104,-1,0.3303999900817871,1.0037000179290771,-0.7766000032424927,0.3617999851703644,0.8108999729156494,-0.8503999710083008,0.3840999901294708,0.6251999735832214,-0.9027000069618225,0.39250001311302185,0.44999998807907104,-0.9225000143051147,0.5976999998092651,1.0037000179290771,-0.5976999998092651,0.6545000076293945,0.8108999729156494,-0.6545000076293945,0.6947000026702881,0.6251999735832214,-0.6947000026702881,0.7099999785423279,0.44999998807907104,-0.7099999785423279,0.7766000032424927,1.0037000179290771,-0.3303999900817871,0.8503999710083008,0.8108999729156494,-0.3617999851703644,0.9027000069618225,0.6251999735832214,-0.3840999901294708,0.9225000143051147,0.44999998807907104,-0.39250001311302185,0.8865000009536743,0.301800012588501,0.37720000743865967,0.9609000086784363,0.301800012588501,0,0.807200014591217,0.19220000505447388,0.3434000015258789,0.875,0.19220000505447388,0,0.7279000282287598,0.11779999732971191,0.30970001220703125,0.7890999913215637,0.11779999732971191,0,0.6919000148773193,0.07500000298023224,0.29440000653266907,0.75,0.07500000298023224,0,0.6822999715805054,0.301800012588501,0.6822999715805054,0.6212999820709229,0.19220000505447388,0.6212999820709229,0.5601999759674072,0.11779999732971191,0.5601999759674072,0.5325000286102295,0.07500000298023224,0.5325000286102295,0.37720000743865967,0.301800012588501,0.8865000009536743,0.3434000015258789,0.19220000505447388,0.807200014591217,0.30970001220703125,0.11779999732971191,0.7279000282287598,0.29440000653266907,0.07500000298023224,0.6919000148773193,0,0.301800012588501,0.9609000086784363,0,0.19220000505447388,0.875,0,0.11779999732971191,0.7890999913215637,0,0.07500000298023224,0.75,-0.37720000743865967,0.301800012588501,0.8865000009536743,-0.3434000015258789,0.19220000505447388,0.807200014591217,-0.30970001220703125,0.11779999732971191,0.7279000282287598,-0.29440000653266907,0.07500000298023224,0.6919000148773193,-0.6822999715805054,0.301800012588501,0.6822999715805054,-0.6212999820709229,0.19220000505447388,0.6212999820709229,-0.5601999759674072,0.11779999732971191,0.5601999759674072,-0.5325000286102295,0.07500000298023224,0.5325000286102295,-0.8865000009536743,0.301800012588501,0.37720000743865967,-0.807200014591217,0.19220000505447388,0.3434000015258789,-0.7279000282287598,0.11779999732971191,0.30970001220703125,-0.6919000148773193,0.07500000298023224,0.29440000653266907,-0.9609000086784363,0.301800012588501,0,-0.875,0.19220000505447388,0,-0.7890999913215637,0.11779999732971191,0,-0.75,0.07500000298023224,0,-0.8865000009536743,0.301800012588501,-0.37720000743865967,-0.807200014591217,0.19220000505447388,-0.3434000015258789,-0.7279000282287598,0.11779999732971191,-0.30970001220703125,-0.6919000148773193,0.07500000298023224,-0.29440000653266907,-0.6822999715805054,0.301800012588501,-0.6822999715805054,-0.6212999820709229,0.19220000505447388,-0.6212999820709229,-0.5601999759674072,0.11779999732971191,-0.5601999759674072,-0.5325000286102295,0.07500000298023224,-0.5325000286102295,-0.37720000743865967,0.301800012588501,-0.8865000009536743,-0.3434000015258789,0.19220000505447388,-0.807200014591217,-0.30970001220703125,0.11779999732971191,-0.7279000282287598,-0.29440000653266907,0.07500000298023224,-0.6919000148773193,0,0.301800012588501,-0.9609000086784363,0,0.19220000505447388,-0.875,0,0.11779999732971191,-0.7890999913215637,0,0.07500000298023224,-0.75,0.37720000743865967,0.301800012588501,-0.8865000009536743,0.3434000015258789,0.19220000505447388,-0.807200014591217,0.30970001220703125,0.11779999732971191,-0.7279000282287598,0.29440000653266907,0.07500000298023224,-0.6919000148773193,0.6822999715805054,0.301800012588501,-0.6822999715805054,0.6212999820709229,0.19220000505447388,-0.6212999820709229,0.5601999759674072,0.11779999732971191,-0.5601999759674072,0.5325000286102295,0.07500000298023224,-0.5325000286102295,0.8865000009536743,0.301800012588501,-0.37720000743865967,0.807200014591217,0.19220000505447388,-0.3434000015258789,0.7279000282287598,0.11779999732971191,-0.30970001220703125,0.6919000148773193,0.07500000298023224,-0.29440000653266907,0.6761999726295471,0.04749999940395355,0.28769999742507935,0.7329999804496765,0.04749999940395355,0,0.5924000144004822,0.023399999365210533,0.25209999084472656,0.6421999931335449,0.023399999365210533,0,0.3853999972343445,0.006399999838322401,0.164000004529953,0.41780000925064087,0.006399999838322401,0,0,0,0,0.5203999876976013,0.04749999940395355,0.5203999876976013,0.4560000002384186,0.023399999365210533,0.4560000002384186,0.29660001397132874,0.006399999838322401,0.29660001397132874,0.28769999742507935,0.04749999940395355,0.6761999726295471,0.25209999084472656,0.023399999365210533,0.5924000144004822,0.164000004529953,0.006399999838322401,0.3853999972343445,0,0.04749999940395355,0.7329999804496765,0,0.023399999365210533,0.6421999931335449,0,0.006399999838322401,0.41780000925064087,-0.28769999742507935,0.04749999940395355,0.6761999726295471,-0.25209999084472656,0.023399999365210533,0.5924000144004822,-0.164000004529953,0.006399999838322401,0.3853999972343445,-0.5203999876976013,0.04749999940395355,0.5203999876976013,-0.4560000002384186,0.023399999365210533,0.4560000002384186,-0.29660001397132874,0.006399999838322401,0.29660001397132874,-0.6761999726295471,0.04749999940395355,0.28769999742507935,-0.5924000144004822,0.023399999365210533,0.25209999084472656,-0.3853999972343445,0.006399999838322401,0.164000004529953,-0.7329999804496765,0.04749999940395355,0,-0.6421999931335449,0.023399999365210533,0,-0.41780000925064087,0.006399999838322401,0,-0.6761999726295471,0.04749999940395355,-0.28769999742507935,-0.5924000144004822,0.023399999365210533,-0.25209999084472656,-0.3853999972343445,0.006399999838322401,-0.164000004529953,-0.5203999876976013,0.04749999940395355,-0.5203999876976013,-0.4560000002384186,0.023399999365210533,-0.4560000002384186,-0.29660001397132874,0.006399999838322401,-0.29660001397132874,-0.28769999742507935,0.04749999940395355,-0.6761999726295471,-0.25209999084472656,0.023399999365210533,-0.5924000144004822,-0.164000004529953,0.006399999838322401,-0.3853999972343445,0,0.04749999940395355,-0.7329999804496765,0,0.023399999365210533,-0.6421999931335449,0,0.006399999838322401,-0.41780000925064087,0.28769999742507935,0.04749999940395355,-0.6761999726295471,0.25209999084472656,0.023399999365210533,-0.5924000144004822,0.164000004529953,0.006399999838322401,-0.3853999972343445,0.5203999876976013,0.04749999940395355,-0.5203999876976013,0.4560000002384186,0.023399999365210533,-0.4560000002384186,0.29660001397132874,0.006399999838322401,-0.29660001397132874,0.6761999726295471,0.04749999940395355,-0.28769999742507935,0.5924000144004822,0.023399999365210533,-0.25209999084472656,0.3853999972343445,0.006399999838322401,-0.164000004529953,-0.800000011920929,1.0125000476837158,0,-0.7922000288963318,1.0300999879837036,0.0843999981880188,-1.0405999422073364,1.027999997138977,0.0843999981880188,-1.0335999727249146,1.010699987411499,0,-1.2229000329971313,1.013800024986267,0.0843999981880188,-1.2063000202178955,0.9983999729156494,0,-1.3351000547409058,0.9751999974250793,0.0843999981880188,-1.3133000135421753,0.9649999737739563,0,-1.3733999729156494,0.8999999761581421,0.0843999981880188,-1.350000023841858,0.8999999761581421,0,-0.7749999761581421,1.0687999725341797,0.11249999701976776,-1.055899977684021,1.066100001335144,0.11249999701976776,-1.2594000101089478,1.047700047492981,0.11249999701976776,-1.3832000494003296,0.9976000189781189,0.11249999701976776,-1.4249999523162842,0.8999999761581421,0.11249999701976776,-0.7577999830245972,1.1073999404907227,0.0843999981880188,-1.0712000131607056,1.104200005531311,0.0843999981880188,-1.2958999872207642,1.0815000534057617,0.0843999981880188,-1.4313000440597534,1.0198999643325806,0.0843999981880188,-1.4766000509262085,0.8999999761581421,0.0843999981880188,-0.75,1.125,0,-1.0780999660491943,1.121500015258789,0,-1.3125,1.0968999862670898,0,-1.4530999660491943,1.0300999879837036,0,-1.5,0.8999999761581421,0,-0.7577999830245972,1.1073999404907227,-0.0843999981880188,-1.0712000131607056,1.104200005531311,-0.0843999981880188,-1.2958999872207642,1.0815000534057617,-0.0843999981880188,-1.4313000440597534,1.0198999643325806,-0.0843999981880188,-1.4766000509262085,0.8999999761581421,-0.0843999981880188,-0.7749999761581421,1.0687999725341797,-0.11249999701976776,-1.055899977684021,1.066100001335144,-0.11249999701976776,-1.2594000101089478,1.047700047492981,-0.11249999701976776,-1.3832000494003296,0.9976000189781189,-0.11249999701976776,-1.4249999523162842,0.8999999761581421,-0.11249999701976776,-0.7922000288963318,1.0300999879837036,-0.0843999981880188,-1.0405999422073364,1.027999997138977,-0.0843999981880188,-1.2229000329971313,1.013800024986267,-0.0843999981880188,-1.3351000547409058,0.9751999974250793,-0.0843999981880188,-1.3733999729156494,0.8999999761581421,-0.0843999981880188,-1.3517999649047852,0.7882000207901001,0.0843999981880188,-1.3305000066757202,0.7979999780654907,0,-1.2839000225067139,0.6600000262260437,0.0843999981880188,-1.2687000036239624,0.675000011920929,0,-1.1655000448226929,0.5333999991416931,0.0843999981880188,-1.1601999998092651,0.5519999861717224,0,-0.9922000169754028,0.42660000920295715,0.0843999981880188,-1.3985999822616577,0.7666000127792358,0.11249999701976776,-1.317199945449829,0.6269999742507935,0.11249999701976776,-1.1770999431610107,0.4925999939441681,0.11249999701976776,-0.9750000238418579,0.375,0.11249999701976776,-1.4455000162124634,0.7448999881744385,0.0843999981880188,-1.3504999876022339,0.5939000248908997,0.0843999981880188,-1.1887999773025513,0.45179998874664307,0.0843999981880188,-0.9577999711036682,0.32339999079704285,0.0843999981880188,-1.4667999744415283,0.7350999712944031,0,-1.3655999898910522,0.5788999795913696,0,-1.194100022315979,0.4332999885082245,0,-0.949999988079071,0.30000001192092896,0,-1.4455000162124634,0.7448999881744385,-0.0843999981880188,-1.3504999876022339,0.5939000248908997,-0.0843999981880188,-1.1887999773025513,0.45179998874664307,-0.0843999981880188,-0.9577999711036682,0.32339999079704285,-0.0843999981880188,-1.3985999822616577,0.7666000127792358,-0.11249999701976776,-1.317199945449829,0.6269999742507935,-0.11249999701976776,-1.1770999431610107,0.4925999939441681,-0.11249999701976776,-0.9750000238418579,0.375,-0.11249999701976776,-1.3517999649047852,0.7882000207901001,-0.0843999981880188,-1.2839000225067139,0.6600000262260437,-0.0843999981880188,-1.1655000448226929,0.5333999991416931,-0.0843999981880188,-0.9922000169754028,0.42660000920295715,-0.0843999981880188,0.8500000238418579,0.7124999761581421,0,0.8500000238418579,0.6480000019073486,0.18559999763965607,1.108199954032898,0.7197999954223633,0.16760000586509705,1.0898000001907349,0.7675999999046326,0,1.2172000408172607,0.8722000122070312,0.12800000607967377,1.1937999725341797,0.8999999761581421,0,1.2792999744415283,1.0505000352859497,0.08829999715089798,1.2508000135421753,1.0605000257492065,0,1.3969000577926636,1.2000000476837158,0.07029999792575836,1.350000023841858,1.2000000476837158,0,0.8500000238418579,0.5062999725341797,0.2475000023841858,1.1483999490737915,0.6146000027656555,0.22349999845027924,1.2687000036239624,0.8108999729156494,0.17059999704360962,1.3422000408172607,1.0283000469207764,0.11779999732971191,1.5,1.2000000476837158,0.09380000084638596,0.8500000238418579,0.3644999861717224,0.18559999763965607,1.1886999607086182,0.5095000267028809,0.16760000586509705,1.3202999830245972,0.7497000098228455,0.12800000607967377,1.4049999713897705,1.0061999559402466,0.08829999715089798,1.6030999422073364,1.2000000476837158,0.07029999792575836,0.8500000238418579,0.30000001192092896,0,1.2070000171661377,0.4616999924182892,0,1.3437000513076782,0.7218999862670898,0,1.4335999488830566,0.9961000084877014,0,1.649999976158142,1.2000000476837158,0,0.8500000238418579,0.3644999861717224,-0.18559999763965607,1.1886999607086182,0.5095000267028809,-0.16760000586509705,1.3202999830245972,0.7497000098228455,-0.12800000607967377,1.4049999713897705,1.0061999559402466,-0.08829999715089798,1.6030999422073364,1.2000000476837158,-0.07029999792575836,0.8500000238418579,0.5062000155448914,-0.2475000023841858,1.1483999490737915,0.6146000027656555,-0.22349999845027924,1.2687000036239624,0.8108999729156494,-0.17059999704360962,1.3422000408172607,1.0283000469207764,-0.11779999732971191,1.5,1.2000000476837158,-0.09380000084638596,0.8500000238418579,0.6480000019073486,-0.18559999763965607,1.108199954032898,0.7197999954223633,-0.16760000586509705,1.2172000408172607,0.8722000122070312,-0.12800000607967377,1.2792999744415283,1.0505000352859497,-0.08829999715089798,1.3969000577926636,1.2000000476837158,-0.07029999792575836,1.4361000061035156,1.222100019454956,0.06589999794960022,1.3859000205993652,1.2210999727249146,0,1.4595999717712402,1.2297999858856201,0.056299999356269836,1.412500023841858,1.2280999422073364,0,1.4602999687194824,1.222499966621399,0.04659999907016754,1.420300006866455,1.2210999727249146,0,1.4312000274658203,1.2000000476837158,0.0421999990940094,1.399999976158142,1.2000000476837158,0,1.5465999841690063,1.2244000434875488,0.08789999783039093,1.5633000135421753,1.2333999872207642,0.07500000298023224,1.54830002784729,1.2257000207901,0.06210000067949295,1.5,1.2000000476837158,0.056299999356269836,1.656999945640564,1.226699948310852,0.06589999794960022,1.6669000387191772,1.2369999885559082,0.056299999356269836,1.6363999843597412,1.2288999557495117,0.04659999907016754,1.5687999725341797,1.2000000476837158,0.0421999990940094,1.707200050354004,1.2276999950408936,0,1.7141000032424927,1.238700032234192,0,1.6763999462127686,1.230299949645996,0,1.600000023841858,1.2000000476837158,0,1.656999945640564,1.226699948310852,-0.06589999794960022,1.6669000387191772,1.2369999885559082,-0.056299999356269836,1.6363999843597412,1.2288999557495117,-0.04659999907016754,1.5687999725341797,1.2000000476837158,-0.0421999990940094,1.5465999841690063,1.2244000434875488,-0.08789999783039093,1.5633000135421753,1.2333999872207642,-0.07500000298023224,1.54830002784729,1.2257000207901,-0.06210000067949295,1.5,1.2000000476837158,-0.056299999356269836,1.4361000061035156,1.222100019454956,-0.06589999794960022,1.4595999717712402,1.2297999858856201,-0.056299999356269836,1.4602999687194824,1.222499966621399,-0.04659999907016754,1.4312000274658203,1.2000000476837158,-0.0421999990940094,0.15719999372959137,1.5504000186920166,0.06700000166893005,0.17030000686645508,1.5504000186920166,0,0,1.5750000476837158,0,0.15000000596046448,1.4905999898910522,0.06390000134706497,0.16249999403953552,1.4905999898910522,0,0.09080000221729279,1.4168000221252441,0.03869999945163727,0.09839999675750732,1.4168000221252441,0,0.09229999780654907,1.350000023841858,0.03929999843239784,0.10000000149011612,1.350000023841858,0,0.12110000103712082,1.5504000186920166,0.12110000103712082,0.11550000309944153,1.4905999898910522,0.11550000309944153,0.06989999860525131,1.4168000221252441,0.06989999860525131,0.07100000232458115,1.350000023841858,0.07100000232458115,0.06700000166893005,1.5504000186920166,0.15719999372959137,0.06390000134706497,1.4905999898910522,0.15000000596046448,0.03869999945163727,1.4168000221252441,0.09080000221729279,0.03929999843239784,1.350000023841858,0.09229999780654907,0,1.5504000186920166,0.17030000686645508,0,1.4905999898910522,0.16249999403953552,0,1.4168000221252441,0.09839999675750732,0,1.350000023841858,0.10000000149011612,-0.06700000166893005,1.5504000186920166,0.15719999372959137,-0.06390000134706497,1.4905999898910522,0.15000000596046448,-0.03869999945163727,1.4168000221252441,0.09080000221729279,-0.03929999843239784,1.350000023841858,0.09229999780654907,-0.12110000103712082,1.5504000186920166,0.12110000103712082,-0.11550000309944153,1.4905999898910522,0.11550000309944153,-0.06989999860525131,1.4168000221252441,0.06989999860525131,-0.07100000232458115,1.350000023841858,0.07100000232458115,-0.15719999372959137,1.5504000186920166,0.06700000166893005,-0.15000000596046448,1.4905999898910522,0.06390000134706497,-0.09080000221729279,1.4168000221252441,0.03869999945163727,-0.09229999780654907,1.350000023841858,0.03929999843239784,-0.17030000686645508,1.5504000186920166,0,-0.16249999403953552,1.4905999898910522,0,-0.09839999675750732,1.4168000221252441,0,-0.10000000149011612,1.350000023841858,0,-0.15719999372959137,1.5504000186920166,-0.06700000166893005,-0.15000000596046448,1.4905999898910522,-0.06390000134706497,-0.09080000221729279,1.4168000221252441,-0.03869999945163727,-0.09229999780654907,1.350000023841858,-0.03929999843239784,-0.12110000103712082,1.5504000186920166,-0.12110000103712082,-0.11550000309944153,1.4905999898910522,-0.11550000309944153,-0.06989999860525131,1.4168000221252441,-0.06989999860525131,-0.07100000232458115,1.350000023841858,-0.07100000232458115,-0.06700000166893005,1.5504000186920166,-0.15719999372959137,-0.06390000134706497,1.4905999898910522,-0.15000000596046448,-0.03869999945163727,1.4168000221252441,-0.09080000221729279,-0.03929999843239784,1.350000023841858,-0.09229999780654907,0,1.5504000186920166,-0.17030000686645508,0,1.4905999898910522,-0.16249999403953552,0,1.4168000221252441,-0.09839999675750732,0,1.350000023841858,-0.10000000149011612,0.06700000166893005,1.5504000186920166,-0.15719999372959137,0.06390000134706497,1.4905999898910522,-0.15000000596046448,0.03869999945163727,1.4168000221252441,-0.09080000221729279,0.03929999843239784,1.350000023841858,-0.09229999780654907,0.12110000103712082,1.5504000186920166,-0.12110000103712082,0.11550000309944153,1.4905999898910522,-0.11550000309944153,0.06989999860525131,1.4168000221252441,-0.06989999860525131,0.07100000232458115,1.350000023841858,-0.07100000232458115,0.15719999372959137,1.5504000186920166,-0.06700000166893005,0.15000000596046448,1.4905999898910522,-0.06390000134706497,0.09080000221729279,1.4168000221252441,-0.03869999945163727,0.09229999780654907,1.350000023841858,-0.03929999843239784,0.21040000021457672,1.3055000305175781,0.08950000256299973,0.2281000018119812,1.3055000305175781,0,0.3804999887943268,1.274999976158142,0.16189999878406525,0.4124999940395355,1.274999976158142,0,0.53329998254776,1.2445000410079956,0.22689999639987946,0.5781000256538391,1.2445000410079956,0,0.5996000170707703,1.2000000476837158,0.2551000118255615,0.6499999761581421,1.2000000476837158,0,0.16200000047683716,1.3055000305175781,0.16200000047683716,0.2928999960422516,1.274999976158142,0.2928999960422516,0.4104999899864197,1.2445000410079956,0.4104999899864197,0.46149998903274536,1.2000000476837158,0.46149998903274536,0.08950000256299973,1.3055000305175781,0.21040000021457672,0.16189999878406525,1.274999976158142,0.3804999887943268,0.22689999639987946,1.2445000410079956,0.53329998254776,0.2551000118255615,1.2000000476837158,0.5996000170707703,0,1.3055000305175781,0.2281000018119812,0,1.274999976158142,0.4124999940395355,0,1.2445000410079956,0.5781000256538391,0,1.2000000476837158,0.6499999761581421,-0.08950000256299973,1.3055000305175781,0.21040000021457672,-0.16189999878406525,1.274999976158142,0.3804999887943268,-0.22689999639987946,1.2445000410079956,0.53329998254776,-0.2551000118255615,1.2000000476837158,0.5996000170707703,-0.16200000047683716,1.3055000305175781,0.16200000047683716,-0.2928999960422516,1.274999976158142,0.2928999960422516,-0.4104999899864197,1.2445000410079956,0.4104999899864197,-0.46149998903274536,1.2000000476837158,0.46149998903274536,-0.21040000021457672,1.3055000305175781,0.08950000256299973,-0.3804999887943268,1.274999976158142,0.16189999878406525,-0.53329998254776,1.2445000410079956,0.22689999639987946,-0.5996000170707703,1.2000000476837158,0.2551000118255615,-0.2281000018119812,1.3055000305175781,0,-0.4124999940395355,1.274999976158142,0,-0.5781000256538391,1.2445000410079956,0,-0.6499999761581421,1.2000000476837158,0,-0.21040000021457672,1.3055000305175781,-0.08950000256299973,-0.3804999887943268,1.274999976158142,-0.16189999878406525,-0.53329998254776,1.2445000410079956,-0.22689999639987946,-0.5996000170707703,1.2000000476837158,-0.2551000118255615,-0.16200000047683716,1.3055000305175781,-0.16200000047683716,-0.2928999960422516,1.274999976158142,-0.2928999960422516,-0.4104999899864197,1.2445000410079956,-0.4104999899864197,-0.46149998903274536,1.2000000476837158,-0.46149998903274536,-0.08950000256299973,1.3055000305175781,-0.21040000021457672,-0.16189999878406525,1.274999976158142,-0.3804999887943268,-0.22689999639987946,1.2445000410079956,-0.53329998254776,-0.2551000118255615,1.2000000476837158,-0.5996000170707703,0,1.3055000305175781,-0.2281000018119812,0,1.274999976158142,-0.4124999940395355,0,1.2445000410079956,-0.5781000256538391,0,1.2000000476837158,-0.6499999761581421,0.08950000256299973,1.3055000305175781,-0.21040000021457672,0.16189999878406525,1.274999976158142,-0.3804999887943268,0.22689999639987946,1.2445000410079956,-0.53329998254776,0.2551000118255615,1.2000000476837158,-0.5996000170707703,0.16200000047683716,1.3055000305175781,-0.16200000047683716,0.2928999960422516,1.274999976158142,-0.2928999960422516,0.4104999899864197,1.2445000410079956,-0.4104999899864197,0.46149998903274536,1.2000000476837158,-0.46149998903274536,0.21040000021457672,1.3055000305175781,-0.08950000256299973,0.3804999887943268,1.274999976158142,-0.16189999878406525,0.53329998254776,1.2445000410079956,-0.22689999639987946,0.5996000170707703,1.2000000476837158,-0.2551000118255615],\"normals\":[-0.9494920694323845,-0.2515364269786189,-0.1876012686200115,-0.96670001745224,-0.2558000087738037,0,-0.8930000066757202,-0.2563000023365021,-0.3698999881744385,-0.8934000134468079,0.25600001215934753,-0.36910000443458557,-0.9667999744415283,0.25540000200271606,0,-0.7260149722024023,0.6725622315424132,-0.14339562350586094,-0.08389999717473984,0.9958000183105469,-0.03550000116229057,-0.09210000187158585,0.9958000183105469,0,0.46895168053340897,0.8783596159888912,0.09256730699733487,0.6297000050544739,0.7318999767303467,0.2603999972343445,0.6819999814033508,0.7312999963760376,0,0.8131828855771891,0.5594560236122703,0.16044485734451933,0.8036999702453613,0.4934000074863434,0.3325999975204468,0.8702999949455261,0.4925000071525574,0,-0.8045241032084407,-0.25135180073328567,-0.5381108060843871,-0.6833999752998352,-0.2567000091075897,-0.6833999752998352,-0.6834999918937683,0.25609999895095825,-0.6834999918937683,-0.6154172153756186,0.6720670779897282,-0.41181002137110273,-0.0649000033736229,0.9958000183105469,-0.0649000033736229,0.39550647488952684,0.8794788320983019,0.2647482053035805,0.4814000129699707,0.7325000166893005,0.4814000129699707,0.6880720658725188,0.5607374353912905,0.4605761182657241,0.614799976348877,0.49399998784065247,0.614799976348877,-0.5381108060843871,-0.25135180073328567,-0.8045241032084407,-0.3698999881744385,-0.2563000023365021,-0.8930000066757202,-0.36910000443458557,0.25600001215934753,-0.8934000134468079,-0.41181002137110273,0.6720670779897282,-0.6154172153756186,-0.03550000116229057,0.9958000183105469,-0.08389999717473984,0.2647482053035805,0.8794788320983019,0.39550647488952684,0.2603999972343445,0.7318999767303467,0.6297000050544739,0.4605761182657241,0.5607374353912905,0.6880720658725188,0.3325999975204468,0.4934000074863434,0.8036999702453613,-0.1876012686200115,-0.2515364269786189,-0.9494920694323845,-0.00279999990016222,-0.2578999996185303,-0.9661999940872192,-0.0019000000320374966,0.2547000050544739,-0.9670000076293945,-0.14339562350586094,0.6725622315424132,-0.7260149722024023,-0.0003000000142492354,0.9957000017166138,-0.09229999780654907,0.09256730699733487,0.8783596159888912,0.46895168053340897,0,0.7312999963760376,0.6820999979972839,0.16044485734451933,0.5594560236122703,0.8131828855771891,0,0.4925000071525574,0.8702999949455261,0.17781356971082418,-0.2762617871652753,-0.94449021137275,0.3790999948978424,-0.35929998755455017,-0.8528000116348267,0.37709999084472656,0.14910000562667847,-0.9140999913215637,0.14395780863022883,0.6540767852077758,-0.7426033317906966,0.027499999850988388,0.9921000003814697,-0.1225999966263771,-0.09276555608813127,0.8766296536816158,0.47213875279382633,-0.26100000739097595,0.7268000245094299,0.6353999972343445,-0.16042337038321952,0.5590076148671953,0.8134954386813597,-0.33250001072883606,0.4925000071525574,0.8043000102043152,0.5155281298975289,-0.3849732031227696,-0.7655235986968341,0.6635000109672546,-0.4108000099658966,-0.6252999901771545,0.7127000093460083,0.07370000332593918,-0.6976000070571899,0.4638206739517661,0.5539062400248373,-0.691417572582934,0.09969999641180038,0.987500011920929,-0.12200000137090683,-0.2749668019071642,0.8694154310328366,0.4104997760424887,-0.48730000853538513,0.723800003528595,0.4885999858379364,-0.46145001001631164,0.5585924142572216,0.6892302974987636,-0.6151999831199646,0.4925999939441681,0.6154999732971191,0.7799397173089967,-0.38252671106395425,-0.495345690085779,0.8799999952316284,-0.3328999876976013,-0.33869999647140503,0.9172999858856201,0.1670999974012375,-0.36149999499320984,0.6935905336506715,0.5583449082267957,-0.4551737416497001,0.1136000007390976,0.9923999905586243,-0.04809999838471413,-0.41112556129251077,0.8694462651166909,0.2739324094125316,-0.6341000199317932,0.7275000214576721,0.26190000772476196,-0.6892193216130235,0.5588149346665281,0.46119691619624625,-0.804099977016449,0.4925999939441681,0.3327000141143799,0.940120720168391,-0.2953801644080805,-0.1700693681540597,0.96670001745224,-0.2556999921798706,0.010499999858438969,0.9674000144004822,0.2529999911785126,0.008100000210106373,0.7547291638439781,0.639985268644528,-0.1442315678392254,0.0934000015258789,0.9955999851226807,0.0013000000035390258,-0.4746532582851164,0.8752533177838288,0.09292961910888725,-0.682200014591217,0.7311999797821045,-0.0003000000142492354,-0.8137112475669765,0.5586976998809986,0.1604084964416667,-0.8702999949455261,0.4925000071525574,-0.00009999999747378752,0.9494920694323845,-0.2515364269786189,0.1876012686200115,0.8930000066757202,-0.2563000023365021,0.3698999881744385,0.8934000134468079,0.25600001215934753,0.36910000443458557,0.7260149722024023,0.6725622315424132,0.14339562350586094,0.08389999717473984,0.9958000183105469,0.03550000116229057,-0.46895168053340897,0.8783596159888912,-0.09256730699733487,-0.6297000050544739,0.7318999767303467,-0.2603999972343445,-0.8131828855771891,0.5594560236122703,-0.16044485734451933,-0.8036999702453613,0.4934000074863434,-0.3325999975204468,0.8045241032084407,-0.25135180073328567,0.5381108060843871,0.6833999752998352,-0.2567000091075897,0.6833999752998352,0.6834999918937683,0.25609999895095825,0.6834999918937683,0.6154172153756186,0.6720670779897282,0.41181002137110273,0.0649000033736229,0.9958000183105469,0.0649000033736229,-0.39550647488952684,0.8794788320983019,-0.2647482053035805,-0.4814000129699707,0.7325000166893005,-0.4814000129699707,-0.6880720658725188,0.5607374353912905,-0.4605761182657241,-0.614799976348877,0.49399998784065247,-0.614799976348877,0.5381108060843871,-0.25135180073328567,0.8045241032084407,0.3698999881744385,-0.2563000023365021,0.8930000066757202,0.36910000443458557,0.25600001215934753,0.8934000134468079,0.41181002137110273,0.6720670779897282,0.6154172153756186,0.03550000116229057,0.9958000183105469,0.08389999717473984,-0.2647482053035805,0.8794788320983019,-0.39550647488952684,-0.2603999972343445,0.7318999767303467,-0.6297000050544739,-0.4605761182657241,0.5607374353912905,-0.6880720658725188,-0.3325999975204468,0.4934000074863434,-0.8036999702453613,0.1876012686200115,-0.2515364269786189,0.9494920694323845,0,-0.2558000087738037,0.96670001745224,0,0.25540000200271606,0.9667999744415283,0.14339562350586094,0.6725622315424132,0.7260149722024023,0,0.9958000183105469,0.09210000187158585,-0.09256730699733487,0.8783596159888912,-0.46895168053340897,0,0.7312999963760376,-0.6819999814033508,-0.16044485734451933,0.5594560236122703,-0.8131828855771891,0,0.4925000071525574,-0.8702999949455261,-0.1876012686200115,-0.2515364269786189,0.9494920694323845,-0.3698999881744385,-0.2563000023365021,0.8930000066757202,-0.36910000443458557,0.25600001215934753,0.8934000134468079,-0.14339562350586094,0.6725622315424132,0.7260149722024023,-0.03550000116229057,0.9958000183105469,0.08389999717473984,0.09256730699733487,0.8783596159888912,-0.46895168053340897,0.2603999972343445,0.7318999767303467,-0.6297000050544739,0.16044485734451933,0.5594560236122703,-0.8131828855771891,0.3325999975204468,0.4934000074863434,-0.8036999702453613,-0.5381108060843871,-0.25135180073328567,0.8045241032084407,-0.6833999752998352,-0.2567000091075897,0.6833999752998352,-0.6834999918937683,0.25609999895095825,0.6834999918937683,-0.41181002137110273,0.6720670779897282,0.6154172153756186,-0.0649000033736229,0.9958000183105469,0.0649000033736229,0.2647482053035805,0.8794788320983019,-0.39550647488952684,0.4814000129699707,0.7325000166893005,-0.4814000129699707,0.4605761182657241,0.5607374353912905,-0.6880720658725188,0.614799976348877,0.49399998784065247,-0.614799976348877,-0.8045241032084407,-0.25135180073328567,0.5381108060843871,-0.8930000066757202,-0.2563000023365021,0.3698999881744385,-0.8934000134468079,0.25600001215934753,0.36910000443458557,-0.6154172153756186,0.6720670779897282,0.41181002137110273,-0.08389999717473984,0.9958000183105469,0.03550000116229057,0.39550647488952684,0.8794788320983019,-0.2647482053035805,0.6297000050544739,0.7318999767303467,-0.2603999972343445,0.6880720658725188,0.5607374353912905,-0.4605761182657241,0.8036999702453613,0.4934000074863434,-0.3325999975204468,-0.9494920694323845,-0.2515364269786189,0.1876012686200115,-0.7260149722024023,0.6725622315424132,0.14339562350586094,0.46895168053340897,0.8783596159888912,-0.09256730699733487,0.8131828855771891,0.5594560236122703,-0.16044485734451933,0.89170186696973,0.4170154906217081,0.175971193734185,0.8453999757766724,0.4034999907016754,0.3497999906539917,0.9153000116348267,0.4027000069618225,0,0.9085685972138349,0.37723739278916374,0.17942980142250198,0.8700000047683716,0.336899995803833,0.36000001430511475,0.9417999982833862,0.3361999988555908,0,0.9398615330526648,0.28672575430335634,0.18560344960982264,0.90420001745224,0.20579999685287476,0.3743000030517578,0.9786999821662903,0.2053000032901764,0,0.974048141581515,0.11941584930670929,0.19227603286929457,0.9218999743461609,-0.06639999896287918,0.38179999589920044,0.9977999925613403,-0.06620000302791595,0,0.7547722509117953,0.41841261984957023,0.5052224547703327,0.6467999815940857,0.4041000008583069,0.6467999815940857,0.7692780597174184,0.3783166747117983,0.5148667404993367,0.6657000184059143,0.33739998936653137,0.6657000184059143,0.7957963785535204,0.28785546405722773,0.5327732685613087,0.6919000148773193,0.2061000019311905,0.6919000148773193,0.8249659082595298,0.1199935753008835,0.5522977386302068,0.7055000066757202,-0.06650000065565109,0.7055000066757202,0.5052224547703327,0.41841261984957023,0.7547722509117953,0.3497999906539917,0.4034999907016754,0.8453999757766724,0.5148667404993367,0.3783166747117983,0.7692780597174184,0.36000001430511475,0.336899995803833,0.8700000047683716,0.5327732685613087,0.28785546405722773,0.7957963785535204,0.3743000030517578,0.20579999685287476,0.90420001745224,0.5522977386302068,0.1199935753008835,0.8249659082595298,0.38179999589920044,-0.06639999896287918,0.9218999743461609,0.175971193734185,0.4170154906217081,0.89170186696973,0,0.4027000069618225,0.9153000116348267,0.17942980142250198,0.37723739278916374,0.9085685972138349,0,0.3361999988555908,0.9417999982833862,0.18560344960982264,0.28672575430335634,0.9398615330526648,0,0.2053000032901764,0.9786999821662903,0.19227603286929457,0.11941584930670929,0.974048141581515,0,-0.06620000302791595,0.9977999925613403,-0.175971193734185,0.4170154906217081,0.89170186696973,-0.3497999906539917,0.4034999907016754,0.8453999757766724,-0.17942980142250198,0.37723739278916374,0.9085685972138349,-0.36000001430511475,0.336899995803833,0.8700000047683716,-0.18560344960982264,0.28672575430335634,0.9398615330526648,-0.3743000030517578,0.20579999685287476,0.90420001745224,-0.19227603286929457,0.11941584930670929,0.974048141581515,-0.38179999589920044,-0.06639999896287918,0.9218999743461609,-0.5052224547703327,0.41841261984957023,0.7547722509117953,-0.6467999815940857,0.4041000008583069,0.6467999815940857,-0.5148667404993367,0.3783166747117983,0.7692780597174184,-0.6657000184059143,0.33739998936653137,0.6657000184059143,-0.5327732685613087,0.28785546405722773,0.7957963785535204,-0.6919000148773193,0.2061000019311905,0.6919000148773193,-0.5522977386302068,0.1199935753008835,0.8249659082595298,-0.7055000066757202,-0.06650000065565109,0.7055000066757202,-0.7547722509117953,0.41841261984957023,0.5052224547703327,-0.8453999757766724,0.4034999907016754,0.3497999906539917,-0.7692780597174184,0.3783166747117983,0.5148667404993367,-0.8700000047683716,0.336899995803833,0.36000001430511475,-0.7957963785535204,0.28785546405722773,0.5327732685613087,-0.90420001745224,0.20579999685287476,0.3743000030517578,-0.8249659082595298,0.1199935753008835,0.5522977386302068,-0.9218999743461609,-0.06639999896287918,0.38179999589920044,-0.89170186696973,0.4170154906217081,0.175971193734185,-0.9153000116348267,0.4027000069618225,0,-0.9085685972138349,0.37723739278916374,0.17942980142250198,-0.9417999982833862,0.3361999988555908,0,-0.9398615330526648,0.28672575430335634,0.18560344960982264,-0.9786999821662903,0.2053000032901764,0,-0.974048141581515,0.11941584930670929,0.19227603286929457,-0.9977999925613403,-0.06620000302791595,0,-0.89170186696973,0.4170154906217081,-0.175971193734185,-0.8453999757766724,0.4034999907016754,-0.3497999906539917,-0.9085685972138349,0.37723739278916374,-0.17942980142250198,-0.8700000047683716,0.336899995803833,-0.36000001430511475,-0.9398615330526648,0.28672575430335634,-0.18560344960982264,-0.90420001745224,0.20579999685287476,-0.3743000030517578,-0.974048141581515,0.11941584930670929,-0.19227603286929457,-0.9218999743461609,-0.06639999896287918,-0.38179999589920044,-0.7547722509117953,0.41841261984957023,-0.5052224547703327,-0.6467999815940857,0.4041000008583069,-0.6467999815940857,-0.7692780597174184,0.3783166747117983,-0.5148667404993367,-0.6657000184059143,0.33739998936653137,-0.6657000184059143,-0.7957963785535204,0.28785546405722773,-0.5327732685613087,-0.6919000148773193,0.2061000019311905,-0.6919000148773193,-0.8249659082595298,0.1199935753008835,-0.5522977386302068,-0.7055000066757202,-0.06650000065565109,-0.7055000066757202,-0.5052224547703327,0.41841261984957023,-0.7547722509117953,-0.3497999906539917,0.4034999907016754,-0.8453999757766724,-0.5148667404993367,0.3783166747117983,-0.7692780597174184,-0.36000001430511475,0.336899995803833,-0.8700000047683716,-0.5327732685613087,0.28785546405722773,-0.7957963785535204,-0.3743000030517578,0.20579999685287476,-0.90420001745224,-0.5522977386302068,0.1199935753008835,-0.8249659082595298,-0.38179999589920044,-0.06639999896287918,-0.9218999743461609,-0.175971193734185,0.4170154906217081,-0.89170186696973,0,0.4027000069618225,-0.9153000116348267,-0.17942980142250198,0.37723739278916374,-0.9085685972138349,0,0.3361999988555908,-0.9417999982833862,-0.18560344960982264,0.28672575430335634,-0.9398615330526648,0,0.2053000032901764,-0.9786999821662903,-0.19227603286929457,0.11941584930670929,-0.974048141581515,0,-0.06620000302791595,-0.9977999925613403,0.175971193734185,0.4170154906217081,-0.89170186696973,0.3497999906539917,0.4034999907016754,-0.8453999757766724,0.17942980142250198,0.37723739278916374,-0.9085685972138349,0.36000001430511475,0.336899995803833,-0.8700000047683716,0.18560344960982264,0.28672575430335634,-0.9398615330526648,0.3743000030517578,0.20579999685287476,-0.90420001745224,0.19227603286929457,0.11941584930670929,-0.974048141581515,0.38179999589920044,-0.06639999896287918,-0.9218999743461609,0.5052224547703327,0.41841261984957023,-0.7547722509117953,0.6467999815940857,0.4041000008583069,-0.6467999815940857,0.5148667404993367,0.3783166747117983,-0.7692780597174184,0.6657000184059143,0.33739998936653137,-0.6657000184059143,0.5327732685613087,0.28785546405722773,-0.7957963785535204,0.6919000148773193,0.2061000019311905,-0.6919000148773193,0.5522977386302068,0.1199935753008835,-0.8249659082595298,0.7055000066757202,-0.06650000065565109,-0.7055000066757202,0.7547722509117953,0.41841261984957023,-0.5052224547703327,0.8453999757766724,0.4034999907016754,-0.3497999906539917,0.7692780597174184,0.3783166747117983,-0.5148667404993367,0.8700000047683716,0.336899995803833,-0.36000001430511475,0.7957963785535204,0.28785546405722773,-0.5327732685613087,0.90420001745224,0.20579999685287476,-0.3743000030517578,0.8249659082595298,0.1199935753008835,-0.5522977386302068,0.9218999743461609,-0.06639999896287918,-0.38179999589920044,0.89170186696973,0.4170154906217081,-0.175971193734185,0.9085685972138349,0.37723739278916374,-0.17942980142250198,0.9398615330526648,0.28672575430335634,-0.18560344960982264,0.974048141581515,0.11941584930670929,-0.19227603286929457,0.949837996375371,-0.25034021126228206,0.18745015141838892,0.8313999772071838,-0.43619999289512634,0.3441999852657318,0.9002000093460083,-0.43549999594688416,0,0.7776228852967049,-0.6097170963557023,0.15345263332507184,0.6735000014305115,-0.6847000122070312,0.2786000072956085,0.7296000123023987,-0.683899998664856,0,0.649169927361788,-0.7497580231546305,0.12822368004526918,0.6403999924659729,-0.7208999991416931,0.26489999890327454,0.6940000057220459,-0.7200000286102295,0,0.7309008795580111,-0.6670453977388504,0.14434106005134031,0.7329000234603882,-0.609000027179718,0.30320000648498535,0.7939000129699707,-0.6079999804496765,0,0.8044401026352556,-0.2509927077580416,0.5384039207922486,0.6360999941825867,-0.4368000030517578,0.6360999941825867,0.6577259751592633,-0.611316221873683,0.4401011457322989,0.5149999856948853,-0.6852999925613403,0.5149999856948853,0.5484574657551682,-0.7513248159850185,0.3670223823454051,0.48969998955726624,-0.7214000225067139,0.48969998955726624,0.6183258124965243,-0.6680727822223783,0.41394679278158897,0.5605999827384949,-0.6096000075340271,0.5605999827384949,0.5384039207922486,-0.2509927077580416,0.8044401026352556,0.3441999852657318,-0.43619999289512634,0.8313999772071838,0.44010114573229886,-0.6113162218736828,0.6577259751592632,0.2786000072956085,-0.6847000122070312,0.6735000014305115,0.3670223823454051,-0.7513248159850185,0.5484574657551682,0.26489999890327454,-0.7208999991416931,0.6403999924659729,0.41394679278158897,-0.6680727822223783,0.6183258124965243,0.30320000648498535,-0.609000027179718,0.7329000234603882,0.18745015141838892,-0.25034021126228206,0.949837996375371,0,-0.43549999594688416,0.9002000093460083,0.15345263332507184,-0.6097170963557023,0.7776228852967049,0,-0.683899998664856,0.7296000123023987,0.12822368004526918,-0.7497580231546305,0.649169927361788,0,-0.7200000286102295,0.6940000057220459,0.14434106005134031,-0.6670453977388504,0.7309008795580111,0,-0.6079999804496765,0.7939000129699707,-0.18745015141838892,-0.25034021126228206,0.949837996375371,-0.3441999852657318,-0.43619999289512634,0.8313999772071838,-0.15345263332507184,-0.6097170963557023,0.7776228852967049,-0.2786000072956085,-0.6847000122070312,0.6735000014305115,-0.12822368004526918,-0.7497580231546305,0.649169927361788,-0.26489999890327454,-0.7208999991416931,0.6403999924659729,-0.14434106005134031,-0.6670453977388504,0.7309008795580111,-0.30320000648498535,-0.609000027179718,0.7329000234603882,-0.5384039207922486,-0.2509927077580416,0.8044401026352556,-0.6360999941825867,-0.4368000030517578,0.6360999941825867,-0.44010114573229886,-0.6113162218736828,0.6577259751592632,-0.5149999856948853,-0.6852999925613403,0.5149999856948853,-0.3670223823454051,-0.7513248159850185,0.5484574657551682,-0.48969998955726624,-0.7214000225067139,0.48969998955726624,-0.41394679278158897,-0.6680727822223783,0.6183258124965243,-0.5605999827384949,-0.6096000075340271,0.5605999827384949,-0.8044401026352556,-0.2509927077580416,0.5384039207922486,-0.8313999772071838,-0.43619999289512634,0.3441999852657318,-0.6577259751592633,-0.611316221873683,0.4401011457322989,-0.6735000014305115,-0.6847000122070312,0.2786000072956085,-0.5484574657551682,-0.7513248159850185,0.3670223823454051,-0.6403999924659729,-0.7208999991416931,0.26489999890327454,-0.6183258124965243,-0.6680727822223783,0.41394679278158897,-0.7329000234603882,-0.609000027179718,0.30320000648498535,-0.949837996375371,-0.25034021126228206,0.18745015141838892,-0.9002000093460083,-0.43549999594688416,0,-0.7776228852967049,-0.6097170963557023,0.15345263332507184,-0.7296000123023987,-0.683899998664856,0,-0.649169927361788,-0.7497580231546305,0.12822368004526918,-0.6940000057220459,-0.7200000286102295,0,-0.7309008795580111,-0.6670453977388504,0.14434106005134031,-0.7939000129699707,-0.6079999804496765,0,-0.949837996375371,-0.25034021126228206,-0.18745015141838892,-0.8313999772071838,-0.43619999289512634,-0.3441999852657318,-0.7776228852967049,-0.6097170963557023,-0.15345263332507184,-0.6735000014305115,-0.6847000122070312,-0.2786000072956085,-0.649169927361788,-0.7497580231546305,-0.12822368004526918,-0.6403999924659729,-0.7208999991416931,-0.26489999890327454,-0.7309008795580111,-0.6670453977388504,-0.14434106005134031,-0.7329000234603882,-0.609000027179718,-0.30320000648498535,-0.8044401026352556,-0.2509927077580416,-0.5384039207922486,-0.6360999941825867,-0.4368000030517578,-0.6360999941825867,-0.6577259751592633,-0.611316221873683,-0.4401011457322989,-0.5149999856948853,-0.6852999925613403,-0.5149999856948853,-0.5484574657551682,-0.7513248159850185,-0.3670223823454051,-0.48969998955726624,-0.7214000225067139,-0.48969998955726624,-0.6183258124965243,-0.6680727822223783,-0.41394679278158897,-0.5605999827384949,-0.6096000075340271,-0.5605999827384949,-0.5384039207922486,-0.2509927077580416,-0.8044401026352556,-0.3441999852657318,-0.43619999289512634,-0.8313999772071838,-0.44010114573229886,-0.6113162218736828,-0.6577259751592632,-0.2786000072956085,-0.6847000122070312,-0.6735000014305115,-0.3670223823454051,-0.7513248159850185,-0.5484574657551682,-0.26489999890327454,-0.7208999991416931,-0.6403999924659729,-0.41394679278158897,-0.6680727822223783,-0.6183258124965243,-0.30320000648498535,-0.609000027179718,-0.7329000234603882,-0.18745015141838892,-0.25034021126228206,-0.949837996375371,0,-0.43549999594688416,-0.9002000093460083,-0.15345263332507184,-0.6097170963557023,-0.7776228852967049,0,-0.683899998664856,-0.7296000123023987,-0.12822368004526918,-0.7497580231546305,-0.649169927361788,0,-0.7200000286102295,-0.6940000057220459,-0.14434106005134031,-0.6670453977388504,-0.7309008795580111,0,-0.6079999804496765,-0.7939000129699707,0.18745015141838892,-0.25034021126228206,-0.949837996375371,0.3441999852657318,-0.43619999289512634,-0.8313999772071838,0.15345263332507184,-0.6097170963557023,-0.7776228852967049,0.2786000072956085,-0.6847000122070312,-0.6735000014305115,0.12822368004526918,-0.7497580231546305,-0.649169927361788,0.26489999890327454,-0.7208999991416931,-0.6403999924659729,0.14434106005134031,-0.6670453977388504,-0.7309008795580111,0.30320000648498535,-0.609000027179718,-0.7329000234603882,0.5384039207922486,-0.2509927077580416,-0.8044401026352556,0.6360999941825867,-0.4368000030517578,-0.6360999941825867,0.44010114573229886,-0.6113162218736828,-0.6577259751592632,0.5149999856948853,-0.6852999925613403,-0.5149999856948853,0.3670223823454051,-0.7513248159850185,-0.5484574657551682,0.48969998955726624,-0.7214000225067139,-0.48969998955726624,0.41394679278158897,-0.6680727822223783,-0.6183258124965243,0.5605999827384949,-0.6096000075340271,-0.5605999827384949,0.8044401026352556,-0.2509927077580416,-0.5384039207922486,0.8313999772071838,-0.43619999289512634,-0.3441999852657318,0.6577259751592633,-0.611316221873683,-0.4401011457322989,0.6735000014305115,-0.6847000122070312,-0.2786000072956085,0.5484574657551682,-0.7513248159850185,-0.3670223823454051,0.6403999924659729,-0.7208999991416931,-0.26489999890327454,0.6183258124965243,-0.6680727822223783,-0.41394679278158897,0.7329000234603882,-0.609000027179718,-0.30320000648498535,0.949837996375371,-0.25034021126228206,-0.18745015141838892,0.7776228852967049,-0.6097170963557023,-0.15345263332507184,0.649169927361788,-0.7497580231546305,-0.12822368004526918,0.7309008795580111,-0.6670453977388504,-0.14434106005134031,0.8387035316725441,-0.518815353093059,0.16555064287077373,0.576200008392334,-0.7817999720573425,0.23819999396800995,0.6238999962806702,-0.781499981880188,0,0.25616783727492487,-0.9653076593733025,0.050588159692990436,0.16359999775886536,-0.9842000007629395,0.06750000268220901,0.17730000615119934,-0.9842000007629395,0,0.07553202574448914,-0.9970317293860195,0.014921249426803469,0.04540000110864639,-0.9987999796867371,0.018699999898672104,0.04919999837875366,-0.9987999796867371,0,0.015316466366009897,-0.9998781173537434,0.003025937076820533,0,-1,0,0.7093394127545394,-0.5208703290912265,0.47490177698703395,0.44040000438690186,-0.7822999954223633,0.44040000438690186,0.21633036433079836,-0.9655254553343809,0.14478179640355507,0.12489999830722809,-0.9843000173568726,0.12489999830722809,0.06371717584979004,-0.9970565493361698,0.04264222001229404,0.034699998795986176,-0.9987999796867371,0.034699998795986176,0.01292177647076656,-0.9998790650449104,0.008653495117885388,0.47490177698703395,-0.5208703290912265,0.7093394127545394,0.23819999396800995,-0.7817999720573425,0.576200008392334,0.14478179640355507,-0.9655254553343809,0.21633036433079836,0.06750000268220901,-0.9842000007629395,0.16359999775886536,0.04264222001229404,-0.9970565493361698,0.06371717584979004,0.018699999898672104,-0.9987999796867371,0.04540000110864639,0.008653495117885388,-0.9998790650449104,0.01292177647076656,0.16555064287077373,-0.5188153530930589,0.838703531672544,0,-0.781499981880188,0.6238999962806702,0.050588159692990436,-0.9653076593733025,0.25616783727492487,0,-0.9842000007629395,0.17730000615119934,0.014921249426803469,-0.9970317293860195,0.07553202574448914,0,-0.9987999796867371,0.04919999837875366,0.003025937076820533,-0.9998781173537434,0.015316466366009897,-0.16555064287077373,-0.5188153530930589,0.838703531672544,-0.23819999396800995,-0.7817999720573425,0.576200008392334,-0.050588159692990436,-0.9653076593733025,0.25616783727492487,-0.06750000268220901,-0.9842000007629395,0.16359999775886536,-0.014921249426803469,-0.9970317293860195,0.07553202574448914,-0.018699999898672104,-0.9987999796867371,0.04540000110864639,-0.003025937076820533,-0.9998781173537434,0.015316466366009897,-0.47490177698703395,-0.5208703290912265,0.7093394127545394,-0.44040000438690186,-0.7822999954223633,0.44040000438690186,-0.14478179640355507,-0.9655254553343809,0.21633036433079836,-0.12489999830722809,-0.9843000173568726,0.12489999830722809,-0.04264222001229404,-0.9970565493361698,0.06371717584979004,-0.034699998795986176,-0.9987999796867371,0.034699998795986176,-0.008653495117885388,-0.9998790650449104,0.01292177647076656,-0.7093394127545394,-0.5208703290912265,0.47490177698703395,-0.576200008392334,-0.7817999720573425,0.23819999396800995,-0.21633036433079836,-0.9655254553343809,0.14478179640355507,-0.16359999775886536,-0.9842000007629395,0.06750000268220901,-0.06371717584979004,-0.9970565493361698,0.04264222001229404,-0.04540000110864639,-0.9987999796867371,0.018699999898672104,-0.01292177647076656,-0.9998790650449104,0.008653495117885388,-0.8387035316725441,-0.518815353093059,0.16555064287077373,-0.6238999962806702,-0.781499981880188,0,-0.25616783727492487,-0.9653076593733025,0.050588159692990436,-0.17730000615119934,-0.9842000007629395,0,-0.07553202574448914,-0.9970317293860195,0.014921249426803469,-0.04919999837875366,-0.9987999796867371,0,-0.015316466366009897,-0.9998781173537434,0.003025937076820533,-0.8387035316725441,-0.518815353093059,-0.16555064287077373,-0.576200008392334,-0.7817999720573425,-0.23819999396800995,-0.25616783727492487,-0.9653076593733025,-0.050588159692990436,-0.16359999775886536,-0.9842000007629395,-0.06750000268220901,-0.07553202574448914,-0.9970317293860195,-0.014921249426803469,-0.04540000110864639,-0.9987999796867371,-0.018699999898672104,-0.015316466366009897,-0.9998781173537434,-0.003025937076820533,-0.7093394127545394,-0.5208703290912265,-0.47490177698703395,-0.44040000438690186,-0.7822999954223633,-0.44040000438690186,-0.21633036433079836,-0.9655254553343809,-0.14478179640355507,-0.12489999830722809,-0.9843000173568726,-0.12489999830722809,-0.06371717584979004,-0.9970565493361698,-0.04264222001229404,-0.034699998795986176,-0.9987999796867371,-0.034699998795986176,-0.01292177647076656,-0.9998790650449104,-0.008653495117885388,-0.47490177698703395,-0.5208703290912265,-0.7093394127545394,-0.23819999396800995,-0.7817999720573425,-0.576200008392334,-0.14478179640355507,-0.9655254553343809,-0.21633036433079836,-0.06750000268220901,-0.9842000007629395,-0.16359999775886536,-0.04264222001229404,-0.9970565493361698,-0.06371717584979004,-0.018699999898672104,-0.9987999796867371,-0.04540000110864639,-0.008653495117885388,-0.9998790650449104,-0.01292177647076656,-0.16555064287077373,-0.5188153530930589,-0.838703531672544,0,-0.781499981880188,-0.6238999962806702,-0.050588159692990436,-0.9653076593733025,-0.25616783727492487,0,-0.9842000007629395,-0.17730000615119934,-0.014921249426803469,-0.9970317293860195,-0.07553202574448914,0,-0.9987999796867371,-0.04919999837875366,-0.003025937076820533,-0.9998781173537434,-0.015316466366009897,0.16555064287077373,-0.5188153530930589,-0.838703531672544,0.23819999396800995,-0.7817999720573425,-0.576200008392334,0.050588159692990436,-0.9653076593733025,-0.25616783727492487,0.06750000268220901,-0.9842000007629395,-0.16359999775886536,0.014921249426803469,-0.9970317293860195,-0.07553202574448914,0.018699999898672104,-0.9987999796867371,-0.04540000110864639,0.003025937076820533,-0.9998781173537434,-0.015316466366009897,0.47490177698703395,-0.5208703290912265,-0.7093394127545394,0.44040000438690186,-0.7822999954223633,-0.44040000438690186,0.14478179640355507,-0.9655254553343809,-0.21633036433079836,0.12489999830722809,-0.9843000173568726,-0.12489999830722809,0.04264222001229404,-0.9970565493361698,-0.06371717584979004,0.034699998795986176,-0.9987999796867371,-0.034699998795986176,0.008653495117885388,-0.9998790650449104,-0.01292177647076656,0.7093394127545394,-0.5208703290912265,-0.47490177698703395,0.576200008392334,-0.7817999720573425,-0.23819999396800995,0.21633036433079836,-0.9655254553343809,-0.14478179640355507,0.16359999775886536,-0.9842000007629395,-0.06750000268220901,0.06371717584979004,-0.9970565493361698,-0.04264222001229404,0.04540000110864639,-0.9987999796867371,-0.018699999898672104,0.01292177647076656,-0.9998790650449104,-0.008653495117885388,0.8387035316725441,-0.518815353093059,-0.16555064287077373,0.25616783727492487,-0.9653076593733025,-0.050588159692990436,0.07553202574448914,-0.9970317293860195,-0.014921249426803469,0.015316466366009897,-0.9998781173537434,-0.003025937076820533,0.007923619032407068,-0.9792649536215844,0.20242867106698378,0.007799999788403511,-1,-0.00019999999494757503,0.007000000216066837,-0.8125,0.5828999876976013,0.03610000014305115,-0.8373000025749207,0.5455999970436096,0.03909999877214432,-0.9991999864578247,-0.0010000000474974513,0.07294431178951416,-0.9771793893951642,0.19949829151861947,0.16179999709129333,-0.8104000091552734,0.5630000233650208,0.17949999868869781,-0.9836999773979187,-0.004399999976158142,0.30508737694808447,-0.9288212891929031,0.2102681744082329,0.48240000009536743,-0.5950999855995178,0.6427000164985657,0.6122999787330627,-0.7906000018119812,-0.010499999858438969,0.85242181732101,-0.45600261568139905,0.2558098118659036,0.7386999726295471,-0.11460000276565552,0.6642000079154968,0.9861999750137329,-0.1657000035047531,-0.0066999997943639755,0.005356055160839852,-0.5906212413030134,0.8069311383227207,-0.0019000000320374966,0.16210000216960907,0.9868000149726868,0.00279999990016222,0.017100000753998756,0.9998000264167786,0.050017369857379264,-0.5919248852555064,0.8044396763759266,0.010499999858438969,0.07339999824762344,0.9972000122070312,0.19813039646486702,-0.5271562130528779,0.8263477918143327,-0.06599999964237213,0.13009999692440033,0.989300012588501,0.4449202026559152,-0.20623851513417835,0.8714996776498938,-0.09440000355243683,0.016599999740719795,0.9954000115394592,-0.005868425724113912,0.5911289942558654,0.8065556854486675,-0.009200000204145908,0.8715000152587891,0.4902999997138977,-0.04859999939799309,0.8406000137329102,0.5394999980926514,-0.0565568733345604,0.5892386602454603,0.8059771221013369,-0.2232999950647354,0.8029000163078308,0.5526999831199646,-0.21826903582935248,0.5064932454046728,0.8341601886673605,-0.5964000225067139,0.5600000023841858,0.5751000046730042,-0.4519125123063575,0.18097256755074448,0.8735124561304479,-0.8033000230789185,0.0681999996304512,0.5916000008583069,-0.010227406140092809,0.9792477063934721,0.20240881820407414,-0.010599999688565731,0.9998999834060669,0.00009999999747378752,-0.058800000697374344,0.9983000159263611,0.000699999975040555,-0.1003582147149349,0.9740903926657386,0.2026724837158167,-0.2806999981403351,0.9598000049591064,0.0032999999821186066,-0.4107606469303811,0.8829429191860411,0.22734883415704424,-0.7497000098228455,0.6617000102996826,0.00430000014603138,-0.905303034236947,0.33387590683454604,0.26258959430409023,-0.9973999857902527,0.07270000129938126,0.002099999925121665,-0.010227406140092809,0.9792477063934721,-0.20240881820407414,-0.008799999952316284,0.8715000152587891,-0.4902999997138977,-0.04650000110268593,0.8411999940872192,-0.5388000011444092,-0.1003582147149349,0.9740903926657386,-0.2026724837158167,-0.21789999306201935,0.8068000078201294,-0.5491999983787537,-0.4107606469303811,0.8829429191860411,-0.22734883415704424,-0.5972999930381775,0.5600000023841858,-0.5741000175476074,-0.905303034236947,0.33387590683454604,-0.26258959430409023,-0.8040000200271606,0.06289999932050705,-0.5913000106811523,-0.005868425724113912,0.5911289942558654,-0.8065556854486675,-0.0017999999690800905,0.16169999539852142,-0.9868000149726868,0.0020000000949949026,0.014600000344216824,-0.9998999834060669,-0.0565568733345604,0.5892386602454603,-0.8059771221013369,0.009200000204145908,0.060100000351667404,-0.998199999332428,-0.21826903582935248,0.5064932454046728,-0.8341601886673605,-0.059300001710653305,0.11389999836683273,-0.9916999936103821,-0.4519125123063575,0.18097256755074448,-0.8735124561304479,-0.0869000032544136,0.012299999594688416,-0.9961000084877014,0.005356055160839852,-0.5906212413030134,-0.8069311383227207,0.006399999838322401,-0.8123999834060669,-0.5831000208854675,0.033799998462200165,-0.8374999761581421,-0.5454000234603882,0.050017369857379264,-0.5919248852555064,-0.8044396763759266,0.15710000693798065,-0.8119000196456909,-0.5622000098228455,0.19813039646486702,-0.5271562130528779,-0.8263477918143327,0.4844000041484833,-0.5893999934196472,-0.6464999914169312,0.4449202026559152,-0.20623851513417835,-0.8714996776498938,0.7389000058174133,-0.10130000114440918,-0.6661999821662903,0.007923619032407068,-0.9792649536215844,-0.20242867106698378,0.07294431178951416,-0.9771793893951642,-0.19949829151861947,0.30508737694808447,-0.9288212891929031,-0.2102681744082329,0.85242181732101,-0.45600261568139905,-0.2558098118659036,0.9478292644663923,0.18220680595344424,0.2615728680221666,0.725600004196167,0.25940001010894775,0.6373999714851379,0.9465000033378601,0.32269999384880066,-0.0034000000450760126,0.8600566042901111,0.44406573291460566,0.25121357898803404,0.6459000110626221,0.4620000123977661,0.607699990272522,0.8258000016212463,0.5638999938964844,-0.007499999832361937,0.722097468072962,0.6564257510605728,0.21835860401454446,0.5315999984741211,0.6366999745368958,0.5586000084877014,0.6499999761581421,0.7598999738693237,-0.006899999920278788,0.5200506551893511,0.8306365796457171,0.1989728338029867,0.42500001192092896,0.6816999912261963,0.5954999923706055,0.5324000120162964,0.8464999794960022,-0.005200000014156103,0.4781972352408055,0.09361119253153362,0.8732493050904043,-0.04960000142455101,-0.01979999989271164,0.9986000061035156,0.4393956565632051,0.2449654752923344,0.8642472868966327,-0.03779999911785126,-0.035599999129772186,0.9986000061035156,0.39562746673558924,0.3918378901601171,0.830627458852191,-0.03790000081062317,-0.0364999994635582,0.9986000061035156,0.3039318735441624,0.5084492756925236,0.8056703732244866,-0.1688999980688095,-0.29789999127388,0.9394999742507935,-0.47742285385863215,-0.09515362565485244,0.8735062713788696,-0.7422999739646912,-0.29919999837875366,0.5995000004768372,-0.42856464276720363,-0.26014738661504994,0.8652489145946263,-0.6195999979972839,-0.5293999910354614,0.5795000195503235,-0.3729119034765285,-0.40703367257705336,0.8338227039568712,-0.4837000072002411,-0.6858000159263611,0.5437999963760376,-0.2896259899317443,-0.5099064991908379,0.8100074987547963,-0.44530001282691956,-0.7943999767303467,0.4131999909877777,-0.9462576942087682,-0.19013883790828634,0.26161727479199826,-0.9265000224113464,-0.37630000710487366,0.0020000000949949026,-0.8154980530103969,-0.5208357818286896,0.25237474894123124,-0.7538999915122986,-0.6570000052452087,0.00430000014603138,-0.6370197706643513,-0.7377648710591707,0.22340279052371467,-0.5662000179290771,-0.8241999745368958,0.0035000001080334187,-0.4721523712289914,-0.8571632880733152,0.2057747212905012,-0.48179998993873596,-0.8762999773025513,0.0019000000320374966,-0.9462576942087682,-0.19013883790828634,-0.26161727479199826,-0.744700014591217,-0.29440000653266907,-0.5989999771118164,-0.8154980530103969,-0.5208357818286896,-0.25237474894123124,-0.6219000220298767,-0.5281000137329102,-0.5781999826431274,-0.6370197706643513,-0.7377648710591707,-0.22340279052371467,-0.4812000095844269,-0.6883000135421753,-0.5428000092506409,-0.4721523712289914,-0.8571632880733152,-0.2057747212905012,-0.43810001015663147,-0.796999990940094,-0.4156999886035919,-0.47742285385863215,-0.09515362565485244,-0.8735062713788696,-0.04430000111460686,-0.017100000753998756,-0.9988999962806702,-0.42856464276720363,-0.26014738661504994,-0.8652489145946263,-0.026200000196695328,-0.028200000524520874,-0.9993000030517578,-0.3729119034765285,-0.40703367257705336,-0.8338227039568712,-0.025299999862909317,-0.028300000354647636,-0.9993000030517578,-0.2896259899317443,-0.5099064991908379,-0.8100074987547963,-0.1574999988079071,-0.28940001130104065,-0.9441999793052673,0.4781972352408055,0.09361119253153362,-0.8732493050904043,0.7282000184059143,0.2524000108242035,-0.6370999813079834,0.4393956565632051,0.2449654752923344,-0.8642472868966327,0.6470999717712402,0.45969998836517334,-0.608299970626831,0.39562746673558924,0.3918378901601171,-0.830627458852191,0.5230000019073486,0.6406999826431274,-0.5622000098228455,0.3039318735441624,0.5084492756925236,-0.8056703732244866,0.4099999964237213,0.6829000115394592,-0.6047000288963318,0.9478292644663923,0.18220680595344424,-0.2615728680221666,0.8600566042901111,0.44406573291460566,-0.25121357898803404,0.722097468072962,0.6564257510605728,-0.21835860401454446,0.5200506551893511,0.8306365796457171,-0.1989728338029867,-0.22469814643301808,0.9251791464063235,0.30586645786099653,-0.23080000281333923,0.9729999899864197,-0.006500000134110451,-0.15289999544620514,0.6872000098228455,0.7102000117301941,-0.3167000114917755,0.6377999782562256,0.7020999789237976,-0.5489000082015991,0.8359000086784363,-0.001500000013038516,-0.7554159687089509,0.6012029555014725,0.260579585761839,-0.6011000275611877,0.4715000092983246,0.6452999711036682,-0.8756999969482422,0.4828000068664551,0.00989999994635582,-0.8962608931532676,0.34737987822914146,0.2757600979213887,-0.6359000205993652,0.44609999656677246,0.629800021648407,-0.8776000142097473,0.47909998893737793,0.019099999219179153,-0.7277298905609964,0.5697090903460769,0.38189102995635527,-0.435699999332428,0.6010000109672546,0.6700000166893005,-0.6962000131607056,0.7174000144004822,0.02449999935925007,-0.06782871702682407,0.42060539852275436,0.9047045727086881,0.11110000312328339,-0.08510000258684158,0.9901999831199646,0.2232999950647354,0.006500000134110451,0.9746999740600586,-0.2397267208313023,0.393118607711727,0.8876873659066373,0.19009999930858612,0.1550000011920929,0.9695000052452087,-0.3269428225776823,0.3199115704344181,0.8892496712774892,0.0052999998442828655,0.18950000405311584,0.9818999767303467,-0.24664197962623152,0.33059209207256196,0.9109756322455285,-0.011800000444054604,0.2467000037431717,0.968999981880188,0.21474893554810956,-0.3917948594999005,0.8946394149322995,0.34389999508857727,-0.7228000164031982,0.599399983882904,0.5724999904632568,-0.5677000284194946,0.5916000008583069,0.5724729014296546,-0.15995477083527343,0.8041699126526359,0.7874000072479248,-0.2565000057220459,0.5605000257492065,0.5277329114283671,-0.01038778030367959,0.8493468480048075,0.6470999717712402,-0.30640000104904175,0.6980999708175659,0.2802675583364272,-0.16422675916009252,0.9457693520726449,0.42750000953674316,-0.4993000030517578,0.753600001335144,0.39159473040680615,-0.8708293307411027,0.2971697222777314,0.4108999967575073,-0.9117000102996826,0.0013000000035390258,0.671500027179718,-0.7409999966621399,-0.0008999999845400453,0.8641399116222908,-0.44467986513529173,0.23563113267282512,0.921999990940094,-0.3871000111103058,-0.007300000172108412,0.9202642753550175,-0.2825130464997946,0.2707398050946873,0.8468999862670898,-0.5315999984741211,-0.013899999670684338,0.6553517759350307,-0.6669930474005048,0.35444932571270243,0.5358999967575073,-0.8442000150680542,-0.010499999858438969,0.39159473040680615,-0.8708293307411027,-0.2971697222777314,0.34119999408721924,-0.7228000164031982,-0.6008999943733215,0.5787000060081482,-0.5611000061035156,-0.5917999744415283,0.8641399116222908,-0.44467986513529173,-0.23563113267282512,0.7849000096321106,-0.25099998712539673,-0.5665000081062317,0.9202642753550175,-0.2825130464997946,-0.2707398050946873,0.6427000164985657,-0.30230000615119934,-0.7039999961853027,0.6553517759350307,-0.6669930474005048,-0.35444932571270243,0.4185999929904938,-0.5,-0.7580999732017517,0.21484877208785355,-0.39190315580348,-0.894568008372541,0.11580000072717667,-0.07909999787807465,-0.9901000261306763,0.23280000686645508,0.012600000016391277,-0.9724000096321106,0.5724729014296546,-0.15995477083527343,-0.8041699126526359,0.20669999718666077,0.15360000729560852,-0.9663000106811523,0.5277329114283671,-0.01038778030367959,-0.8493468480048075,0.02449999935925007,0.16140000522136688,-0.9865999817848206,0.2802675583364272,-0.16422675916009252,-0.9457693520726449,0.0034000000450760126,0.2110999971628189,-0.9775000214576721,-0.06785298017190203,0.4204621294822817,-0.9047693467138552,-0.13490000367164612,0.6875,-0.7135999798774719,-0.31949999928474426,0.6330999732017517,-0.7050999999046326,-0.2397267208313023,0.393118607711727,-0.8876873659066373,-0.6039000153541565,0.46140000224113464,-0.6499000191688538,-0.3269428225776823,0.3199115704344181,-0.8892496712774892,-0.6317999958992004,0.43720000982284546,-0.6401000022888184,-0.24664197962623152,0.33059209207256196,-0.9109756322455285,-0.4242999851703644,0.6126999855041504,-0.666700005531311,-0.22469814643301808,0.9251791464063235,-0.30586645786099653,-0.7554159687089509,0.6012029555014725,-0.260579585761839,-0.8962608931532676,0.34737987822914146,-0.2757600979213887,-0.7277298905609964,0.5697090903460769,-0.38189102995635527,-0.4581346849192706,0.8290808733288989,0.32052693483404915,-0.2599000036716461,0.7918999791145325,0.5525000095367432,-0.42579999566078186,0.9047999978065491,0.01080000028014183,-0.246185208210748,0.9533009586111941,0.17495749646473896,0.009499999694526196,0.9997000098228455,-0.021700000390410423,0.02199999988079071,0.9998000264167786,0.0015999999595806003,0.5588645441304007,0.6666977641221954,-0.49313741759106583,0.41019999980926514,0.3328999876976013,-0.8490999937057495,0.9995999932289124,0.02590000070631504,0.011599999852478504,0.6055606832628622,-0.6381346851214208,-0.47547910840666874,0.5414999723434448,-0.5486000180244446,-0.6370000243186951,0.7095999717712402,-0.7045999765396118,0.009700000286102295,-0.18304741452057446,0.5222477728722519,0.8329171073806239,0.046300001442432404,0.4551999866962433,0.88919997215271,-0.11108392464029737,0.8826749299553293,0.45666763593981924,-0.010700000450015068,0.9887999892234802,0.14890000224113464,0.07555097805976921,0.8081131026014043,-0.5841620178667426,-0.04439999908208847,0.6829000115394592,-0.7290999889373779,0.1865265036320752,-0.09254615883689393,-0.9780813217352277,0.12280000001192093,0.009200000204145908,-0.9923999905586243,0.20586843545090303,-0.21233995694823685,0.9552643246600484,0.48179998993873596,-0.18039999902248383,0.8575000166893005,0.11889342221748984,0.6798112027299875,0.723685762466156,0.4553000032901764,0.7366999983787537,0.4999000132083893,-0.10639578264983571,0.9027074902947484,-0.4168922215634223,-0.22050000727176666,0.9071999788284302,-0.35830000042915344,-0.16898371149150437,0.5156251093433941,-0.8399852688381916,-0.23589999973773956,0.6572999954223633,-0.7157999873161316,0.4290978121327757,-0.8521036390277623,0.29965723081299106,0.7281000018119812,-0.6852999925613403,-0.015599999576807022,0.7436424021085918,-0.3226049926539566,0.5855954204917456,0.888700008392334,0.45809999108314514,-0.016699999570846558,-0.2121657419347905,0.9655431048711052,-0.15070570853529733,-0.26010000705718994,0.9656000137329102,0.0007999999797903001,-0.3585820114624871,0.8925522270977658,-0.2734400536833164,-0.3716000020503998,0.9283999800682068,-0.004399999976158142,0.4290978121327757,-0.8521036390277623,-0.29965723081299106,0.48019999265670776,-0.17839999496936798,-0.8589000105857849,0.7436424021085918,-0.3226049926539566,-0.5855954204917456,0.48809999227523804,0.7167999744415283,-0.49790000915527344,-0.2121657419347905,0.9655431048711052,0.15070570853529733,-0.22200000286102295,0.9053999781608582,0.3619000017642975,-0.3585820114624871,0.8925522270977658,0.2734400536833164,-0.2354000061750412,0.6632000207901001,0.7105000019073486,0.20586843545090303,-0.21233995694823685,-0.9552643246600484,0.05869999900460243,0.4377000033855438,-0.8971999883651733,0.11889342221748984,0.6798112027299875,-0.723685762466156,0.0013000000035390258,0.9865000247955322,-0.164000004529953,-0.10639578264983571,0.9027074902947484,0.4168922215634223,-0.044199999421834946,0.6816999912261963,0.7303000092506409,-0.16898371149150437,0.5156251093433941,0.8399852688381916,0.1387999951839447,-0.03420000150799751,0.9897000193595886,-0.18304741452057446,0.5222477728722519,-0.8329171073806239,-0.258899986743927,0.7972000241279602,-0.5454000234603882,-0.11108392464029737,0.8826749299553293,-0.45666763593981924,0.012299999594688416,0.9997000098228455,0.019300000742077827,0.07555097805976921,0.8081131026014043,0.5841620178667426,0.3986000120639801,0.3549000024795532,0.8457000255584717,0.1865265036320752,-0.09254615883689393,0.9780813217352277,0.5375999808311462,-0.5813999772071838,0.6107000112533569,-0.4581346849192706,0.8290808733288989,-0.32052693483404915,-0.246185208210748,0.9533009586111941,-0.17495749646473896,0.5588645441304007,0.6666977641221954,0.49313741759106583,0.6055606832628622,-0.6381346851214208,0.47547910840666874,0.14291142372842203,0.9893409658361559,0.02794241017337756,0.7626000046730042,0.5649999976158142,0.3147999942302704,0.8245000243186951,0.5658000111579895,0,0,1,0,0.973458284214919,-0.12702375109433608,0.1903784009578562,0.8479999899864197,-0.39800000190734863,0.3499999940395355,0.9176999926567078,-0.39730000495910645,0,0.746764468277477,-0.6487991657292128,0.14629583544084326,0.8640999794006348,-0.35530000925064087,0.3564000129699707,0.9352999925613403,-0.3538999855518341,0.00009999999747378752,0.981025828088616,0.023627540802087,0.19243197223614078,0.7210000157356262,0.6255999803543091,0.29789999127388,0.7807000279426575,0.6248999834060669,0.00009999999747378752,0.12055154584358733,0.9894424773820601,0.08044195886956569,0.5834000110626221,0.5651999711990356,0.583299994468689,0.8246900772851533,-0.12832997885984362,0.5508336345515219,0.6485000252723694,-0.3986999988555908,0.6484000086784363,0.6311228589976491,-0.650668419605885,0.422273068734218,0.6608999967575073,-0.35589998960494995,0.6607000231742859,0.8301974890908831,0.023243924461984086,0.5569846039908094,0.5519000291824341,0.6252999901771545,0.551800012588501,0.08044195886956569,0.9894424773820601,0.12055154584358733,0.3147999942302704,0.5651000142097473,0.7626000046730042,0.5508336345515219,-0.12832997885984362,0.8246900772851533,0.3499999940395355,-0.39800000190734863,0.8479999899864197,0.422273068734218,-0.650668419605885,0.6311228589976491,0.3564999997615814,-0.35519999265670776,0.8641999959945679,0.5569846039908094,0.023243924461984086,0.8301974890908831,0.2980000078678131,0.6255000233650208,0.7210999727249146,0.02794241017337756,0.9893409658361559,0.14291142372842203,0,0.5658000111579895,0.8245000243186951,0.1903784009578562,-0.12702375109433608,0.973458284214919,0,-0.39730000495910645,0.9176999926567078,0.14629583544084326,-0.6487991657292128,0.746764468277477,-0.00009999999747378752,-0.3538999855518341,0.9352999925613403,0.19243197223614078,0.023627540802087,0.981025828088616,-0.00009999999747378752,0.6248999834060669,0.7807000279426575,-0.02794241017337756,0.9893409658361559,0.14291142372842203,-0.3147999942302704,0.5649999976158142,0.7626000046730042,-0.1903784009578562,-0.12702375109433608,0.973458284214919,-0.3499999940395355,-0.39800000190734863,0.8479999899864197,-0.14629583544084326,-0.6487991657292128,0.746764468277477,-0.3564000129699707,-0.35530000925064087,0.8640999794006348,-0.19243197223614078,0.023627540802087,0.981025828088616,-0.29789999127388,0.6255999803543091,0.7210000157356262,-0.08044195886956569,0.9894424773820601,0.12055154584358733,-0.583299994468689,0.5651999711990356,0.5834000110626221,-0.5508336345515219,-0.12832997885984362,0.8246900772851533,-0.6484000086784363,-0.3986999988555908,0.6485000252723694,-0.422273068734218,-0.650668419605885,0.6311228589976491,-0.6607000231742859,-0.35589998960494995,0.6608999967575073,-0.5569846039908094,0.023243924461984086,0.8301974890908831,-0.551800012588501,0.6252999901771545,0.5519000291824341,-0.12055154584358733,0.9894424773820601,0.08044195886956569,-0.7626000046730042,0.5651000142097473,0.3147999942302704,-0.8246900772851533,-0.12832997885984362,0.5508336345515219,-0.8479999899864197,-0.39800000190734863,0.3499999940395355,-0.6311228589976491,-0.650668419605885,0.422273068734218,-0.8641999959945679,-0.35519999265670776,0.3564999997615814,-0.8301974890908831,0.023243924461984086,0.5569846039908094,-0.7210999727249146,0.6255000233650208,0.2980000078678131,-0.14291142372842203,0.9893409658361559,0.02794241017337756,-0.8245000243186951,0.5658000111579895,0,-0.973458284214919,-0.12702375109433608,0.1903784009578562,-0.9176999926567078,-0.39730000495910645,0,-0.746764468277477,-0.6487991657292128,0.14629583544084326,-0.9352999925613403,-0.3538999855518341,-0.00009999999747378752,-0.981025828088616,0.023627540802087,0.19243197223614078,-0.7807000279426575,0.6248999834060669,-0.00009999999747378752,-0.14291142372842203,0.9893409658361559,-0.02794241017337756,-0.7626000046730042,0.5649999976158142,-0.3147999942302704,-0.973458284214919,-0.12702375109433608,-0.1903784009578562,-0.8479999899864197,-0.39800000190734863,-0.3499999940395355,-0.746764468277477,-0.6487991657292128,-0.14629583544084326,-0.8640999794006348,-0.35530000925064087,-0.3564000129699707,-0.981025828088616,0.023627540802087,-0.19243197223614078,-0.7210000157356262,0.6255999803543091,-0.29789999127388,-0.12055154584358733,0.9894424773820601,-0.08044195886956569,-0.5834000110626221,0.5651999711990356,-0.583299994468689,-0.8246900772851533,-0.12832997885984362,-0.5508336345515219,-0.6485000252723694,-0.3986999988555908,-0.6484000086784363,-0.6311228589976491,-0.650668419605885,-0.422273068734218,-0.6608999967575073,-0.35589998960494995,-0.6607000231742859,-0.8301974890908831,0.023243924461984086,-0.5569846039908094,-0.5519000291824341,0.6252999901771545,-0.551800012588501,-0.08044195886956569,0.9894424773820601,-0.12055154584358733,-0.3147999942302704,0.5651000142097473,-0.7626000046730042,-0.5508336345515219,-0.12832997885984362,-0.8246900772851533,-0.3499999940395355,-0.39800000190734863,-0.8479999899864197,-0.422273068734218,-0.650668419605885,-0.6311228589976491,-0.3564999997615814,-0.35519999265670776,-0.8641999959945679,-0.5569846039908094,0.023243924461984086,-0.8301974890908831,-0.2980000078678131,0.6255000233650208,-0.7210999727249146,-0.02794241017337756,0.9893409658361559,-0.14291142372842203,0,0.5658000111579895,-0.8245000243186951,-0.1903784009578562,-0.12702375109433608,-0.973458284214919,0,-0.39730000495910645,-0.9176999926567078,-0.14629583544084326,-0.6487991657292128,-0.746764468277477,0.00009999999747378752,-0.3538999855518341,-0.9352999925613403,-0.19243197223614078,0.023627540802087,-0.981025828088616,0.00009999999747378752,0.6248999834060669,-0.7807000279426575,0.02794241017337756,0.9893409658361559,-0.14291142372842203,0.3147999942302704,0.5649999976158142,-0.7626000046730042,0.1903784009578562,-0.12702375109433608,-0.973458284214919,0.3499999940395355,-0.39800000190734863,-0.8479999899864197,0.14629583544084326,-0.6487991657292128,-0.746764468277477,0.3564000129699707,-0.35530000925064087,-0.8640999794006348,0.19243197223614078,0.023627540802087,-0.981025828088616,0.29789999127388,0.6255999803543091,-0.7210000157356262,0.08044195886956569,0.9894424773820601,-0.12055154584358733,0.583299994468689,0.5651999711990356,-0.5834000110626221,0.5508336345515219,-0.12832997885984362,-0.8246900772851533,0.6484000086784363,-0.3986999988555908,-0.6485000252723694,0.422273068734218,-0.650668419605885,-0.6311228589976491,0.6607000231742859,-0.35589998960494995,-0.6608999967575073,0.5569846039908094,0.023243924461984086,-0.8301974890908831,0.551800012588501,0.6252999901771545,-0.5519000291824341,0.12055154584358733,0.9894424773820601,-0.08044195886956569,0.7626000046730042,0.5651000142097473,-0.3147999942302704,0.8246900772851533,-0.12832997885984362,-0.5508336345515219,0.8479999899864197,-0.39800000190734863,-0.3499999940395355,0.6311228589976491,-0.650668419605885,-0.422273068734218,0.8641999959945679,-0.35519999265670776,-0.3564999997615814,0.8301974890908831,0.023243924461984086,-0.5569846039908094,0.7210999727249146,0.6255000233650208,-0.2980000078678131,0.14291142372842203,0.9893409658361559,-0.02794241017337756,0.973458284214919,-0.12702375109433608,-0.1903784009578562,0.746764468277477,-0.6487991657292128,-0.14629583544084326,0.981025828088616,0.023627540802087,-0.19243197223614078,0.3275777539387444,0.9426132072697088,0.06459997372414784,0.21799999475479126,0.9718000292778015,0.09019999951124191,0.23659999668598175,0.9715999960899353,0,0.16309406473662258,0.9860835381794821,0.03224254610169826,0.15960000455379486,0.9850000143051147,0.06599999964237213,0.17309999465942383,0.9848999977111816,0,0.18099512760445208,0.982833937027952,0.035752146922720544,0.3504999876022339,0.9253000020980835,0.14470000565052032,0.3797000050544739,0.9251000285148621,0,0.5235316128339348,0.8457082744477594,0.10340292497841669,0.48559999465942383,0.8507000207901001,0.20149999856948853,0.5267000198364258,0.8500999808311462,0,0.27649957959472143,0.9430486026192276,0.18495219809957497,0.16660000383853912,0.9718000292778015,0.16660000383853912,0.13770263578303485,0.9861891086646662,0.09202731143305214,0.12189999967813492,0.9850000143051147,0.12189999967813492,0.15275889985296257,0.9829686899991592,0.1021629727300915,0.2676999866962433,0.925599992275238,0.2676999866962433,0.44245158541572593,0.8465383737127242,0.29598881126645027,0.37130001187324524,0.8510000109672546,0.37130001187324524,0.18495219809957497,0.9430486026192276,0.27649957959472143,0.09019999951124191,0.9718000292778015,0.21799999475479126,0.09202731143305214,0.9861891086646662,0.13770263578303485,0.06599999964237213,0.9850000143051147,0.15960000455379486,0.1021629727300915,0.9829686899991592,0.15275889985296257,0.14470000565052032,0.9253000020980835,0.3504999876022339,0.29598881126645027,0.8465383737127242,0.44245158541572593,0.20149999856948853,0.8507000207901001,0.48559999465942383,0.06459997372414784,0.9426132072697088,0.3275777539387444,0,0.9715999960899353,0.23659999668598175,0.03224254610169826,0.9860835381794821,0.16309406473662258,0,0.9848999977111816,0.17309999465942383,0.035752146922720544,0.982833937027952,0.18099512760445208,0,0.9251000285148621,0.3797000050544739,0.1034029249784167,0.8457082744477595,0.5235316128339349,0,0.8500999808311462,0.5267000198364258,-0.06459997372414784,0.9426132072697088,0.3275777539387444,-0.09019999951124191,0.9718000292778015,0.21799999475479126,-0.03224254610169826,0.9860835381794821,0.16309406473662258,-0.06599999964237213,0.9850000143051147,0.15960000455379486,-0.035752146922720544,0.982833937027952,0.18099512760445208,-0.14470000565052032,0.9253000020980835,0.3504999876022339,-0.1034029249784167,0.8457082744477595,0.5235316128339349,-0.20149999856948853,0.8507000207901001,0.48559999465942383,-0.18495219809957497,0.9430486026192276,0.27649957959472143,-0.16660000383853912,0.9718000292778015,0.16660000383853912,-0.09202731143305214,0.9861891086646662,0.13770263578303485,-0.12189999967813492,0.9850000143051147,0.12189999967813492,-0.1021629727300915,0.9829686899991592,0.15275889985296257,-0.2676999866962433,0.925599992275238,0.2676999866962433,-0.29598881126645027,0.8465383737127242,0.44245158541572593,-0.37130001187324524,0.8510000109672546,0.37130001187324524,-0.27649957959472143,0.9430486026192276,0.18495219809957497,-0.21799999475479126,0.9718000292778015,0.09019999951124191,-0.13770263578303485,0.9861891086646662,0.09202731143305214,-0.15960000455379486,0.9850000143051147,0.06599999964237213,-0.15275889985296257,0.9829686899991592,0.1021629727300915,-0.3504999876022339,0.9253000020980835,0.14470000565052032,-0.44245158541572593,0.8465383737127242,0.29598881126645027,-0.48559999465942383,0.8507000207901001,0.20149999856948853,-0.3275777539387444,0.9426132072697088,0.06459997372414784,-0.23659999668598175,0.9715999960899353,0,-0.16309406473662258,0.9860835381794821,0.03224254610169826,-0.17309999465942383,0.9848999977111816,0,-0.18099512760445208,0.982833937027952,0.035752146922720544,-0.3797000050544739,0.9251000285148621,0,-0.5235316128339348,0.8457082744477594,0.10340292497841669,-0.5267000198364258,0.8500999808311462,0,-0.3275777539387444,0.9426132072697088,-0.06459997372414784,-0.21799999475479126,0.9718000292778015,-0.09019999951124191,-0.16309406473662258,0.9860835381794821,-0.03224254610169826,-0.15960000455379486,0.9850000143051147,-0.06599999964237213,-0.18099512760445208,0.982833937027952,-0.035752146922720544,-0.3504999876022339,0.9253000020980835,-0.14470000565052032,-0.5235316128339348,0.8457082744477594,-0.10340292497841669,-0.48559999465942383,0.8507000207901001,-0.20149999856948853,-0.27649957959472143,0.9430486026192276,-0.18495219809957497,-0.16660000383853912,0.9718000292778015,-0.16660000383853912,-0.13770263578303485,0.9861891086646662,-0.09202731143305214,-0.12189999967813492,0.9850000143051147,-0.12189999967813492,-0.15275889985296257,0.9829686899991592,-0.1021629727300915,-0.2676999866962433,0.925599992275238,-0.2676999866962433,-0.44245158541572593,0.8465383737127242,-0.29598881126645027,-0.37130001187324524,0.8510000109672546,-0.37130001187324524,-0.18495219809957497,0.9430486026192276,-0.27649957959472143,-0.09019999951124191,0.9718000292778015,-0.21799999475479126,-0.09202731143305214,0.9861891086646662,-0.13770263578303485,-0.06599999964237213,0.9850000143051147,-0.15960000455379486,-0.1021629727300915,0.9829686899991592,-0.15275889985296257,-0.14470000565052032,0.9253000020980835,-0.3504999876022339,-0.29598881126645027,0.8465383737127242,-0.44245158541572593,-0.20149999856948853,0.8507000207901001,-0.48559999465942383,-0.06459997372414784,0.9426132072697088,-0.3275777539387444,0,0.9715999960899353,-0.23659999668598175,-0.03224254610169826,0.9860835381794821,-0.16309406473662258,0,0.9848999977111816,-0.17309999465942383,-0.035752146922720544,0.982833937027952,-0.18099512760445208,0,0.9251000285148621,-0.3797000050544739,-0.1034029249784167,0.8457082744477595,-0.5235316128339349,0,0.8500999808311462,-0.5267000198364258,0.06459997372414784,0.9426132072697088,-0.3275777539387444,0.09019999951124191,0.9718000292778015,-0.21799999475479126,0.03224254610169826,0.9860835381794821,-0.16309406473662258,0.06599999964237213,0.9850000143051147,-0.15960000455379486,0.035752146922720544,0.982833937027952,-0.18099512760445208,0.14470000565052032,0.9253000020980835,-0.3504999876022339,0.1034029249784167,0.8457082744477595,-0.5235316128339349,0.20149999856948853,0.8507000207901001,-0.48559999465942383,0.18495219809957497,0.9430486026192276,-0.27649957959472143,0.16660000383853912,0.9718000292778015,-0.16660000383853912,0.09202731143305214,0.9861891086646662,-0.13770263578303485,0.12189999967813492,0.9850000143051147,-0.12189999967813492,0.1021629727300915,0.9829686899991592,-0.15275889985296257,0.2676999866962433,0.925599992275238,-0.2676999866962433,0.29598881126645027,0.8465383737127242,-0.44245158541572593,0.37130001187324524,0.8510000109672546,-0.37130001187324524,0.27649957959472143,0.9430486026192276,-0.18495219809957497,0.21799999475479126,0.9718000292778015,-0.09019999951124191,0.13770263578303485,0.9861891086646662,-0.09202731143305214,0.15960000455379486,0.9850000143051147,-0.06599999964237213,0.15275889985296257,0.9829686899991592,-0.1021629727300915,0.3504999876022339,0.9253000020980835,-0.14470000565052032,0.44245158541572593,0.8465383737127242,-0.29598881126645027,0.48559999465942383,0.8507000207901001,-0.20149999856948853,0.3275777539387444,0.9426132072697088,-0.06459997372414784,0.16309406473662258,0.9860835381794821,-0.03224254610169826,0.18099512760445208,0.982833937027952,-0.035752146922720544,0.5235316128339348,0.8457082744477594,-0.10340292497841669],\"uvs\":[[2,2,1.75,2,1.75,1.975000023841858,2,1.975000023841858,1.75,1.9500000476837158,2,1.9500000476837158,1.75,1.9249999523162842,2,1.9249999523162842,1.75,1.899999976158142,2,1.899999976158142,1.5,2,1.5,1.975000023841858,1.5,1.9500000476837158,1.5,1.9249999523162842,1.5,1.899999976158142,1.25,2,1.25,1.975000023841858,1.25,1.9500000476837158,1.25,1.9249999523162842,1.25,1.899999976158142,1,2,1,1.975000023841858,1,1.9500000476837158,1,1.9249999523162842,1,1.899999976158142,0.75,2,0.75,1.975000023841858,0.75,1.9500000476837158,0.75,1.9249999523162842,0.75,1.899999976158142,0.5,2,0.5,1.975000023841858,0.5,1.9500000476837158,0.5,1.9249999523162842,0.5,1.899999976158142,0.25,2,0.25,1.975000023841858,0.25,1.9500000476837158,0.25,1.9249999523162842,0.25,1.899999976158142,0,2,0,1.975000023841858,0,1.9500000476837158,0,1.9249999523162842,0,1.899999976158142,1.75,1.6749999523162842,2,1.6749999523162842,1.75,1.4500000476837158,2,1.4500000476837158,1.75,1.225000023841858,2,1.225000023841858,1.75,1,2,1,1.5,1.6749999523162842,1.5,1.4500000476837158,1.5,1.225000023841858,1.5,1,1.25,1.6749999523162842,1.25,1.4500000476837158,1.25,1.225000023841858,1.25,1,1,1.6749999523162842,1,1.4500000476837158,1,1.225000023841858,1,1,0.75,1.6749999523162842,0.75,1.4500000476837158,0.75,1.225000023841858,0.75,1,0.5,1.6749999523162842,0.5,1.4500000476837158,0.5,1.225000023841858,0.5,1,0.25,1.6749999523162842,0.25,1.4500000476837158,0.25,1.225000023841858,0.25,1,0,1.6749999523162842,0,1.4500000476837158,0,1.225000023841858,0,1,1.75,0.8500000238418579,2,0.8500000238418579,1.75,0.699999988079071,2,0.699999988079071,1.75,0.550000011920929,2,0.550000011920929,1.75,0.4000000059604645,2,0.4000000059604645,1.5,0.8500000238418579,1.5,0.699999988079071,1.5,0.550000011920929,1.5,0.4000000059604645,1.25,0.8500000238418579,1.25,0.699999988079071,1.25,0.550000011920929,1.25,0.4000000059604645,1,0.8500000238418579,1,0.699999988079071,1,0.550000011920929,1,0.4000000059604645,0.75,0.8500000238418579,0.75,0.699999988079071,0.75,0.550000011920929,0.75,0.4000000059604645,0.5,0.8500000238418579,0.5,0.699999988079071,0.5,0.550000011920929,0.5,0.4000000059604645,0.25,0.8500000238418579,0.25,0.699999988079071,0.25,0.550000011920929,0.25,0.4000000059604645,0,0.8500000238418579,0,0.699999988079071,0,0.550000011920929,0,0.4000000059604645,1.75,0.30000001192092896,2,0.30000001192092896,1.75,0.20000000298023224,2,0.20000000298023224,1.75,0.10000000149011612,2,0.10000000149011612,1.75,0,1.5,0.30000001192092896,1.5,0.20000000298023224,1.5,0.10000000149011612,1.5,0,1.25,0.30000001192092896,1.25,0.20000000298023224,1.25,0.10000000149011612,1.25,0,1,0.30000001192092896,1,0.20000000298023224,1,0.10000000149011612,1,0,0.75,0.30000001192092896,0.75,0.20000000298023224,0.75,0.10000000149011612,0.75,0,0.5,0.30000001192092896,0.5,0.20000000298023224,0.5,0.10000000149011612,0.5,0,0.25,0.30000001192092896,0.25,0.20000000298023224,0.25,0.10000000149011612,0.25,0,0,0.30000001192092896,0,0.20000000298023224,0,0.10000000149011612,0,0,0.875,1,0.875,0.875,1,0.875,0.875,0.75,1,0.75,0.875,0.625,1,0.625,0.875,0.5,1,0.5,0.75,0.875,0.75,0.75,0.75,0.625,0.75,0.5,0.625,1,0.625,0.875,0.625,0.75,0.625,0.625,0.625,0.5,0.5,0.875,0.5,0.75,0.5,0.625,0.5,0.5,0.375,1,0.375,0.875,0.375,0.75,0.375,0.625,0.375,0.5,0.25,0.875,0.25,0.75,0.25,0.625,0.25,0.5,0.125,1,0.125,0.875,0.125,0.75,0.125,0.625,0.125,0.5,0,0.875,0,0.75,0,0.625,0,0.5,0.875,0.375,1,0.375,0.875,0.25,1,0.25,0.875,0.125,1,0.125,0.875,0,0.75,0.375,0.75,0.25,0.75,0.125,0.625,0.375,0.625,0.25,0.625,0.125,0.625,0,0.5,0.375,0.5,0.25,0.5,0.125,0.375,0.375,0.375,0.25,0.375,0.125,0.375,0,0.25,0.375,0.25,0.25,0.25,0.125,0.125,0.375,0.125,0.25,0.125,0.125,0.125,0,0,0.375,0,0.25,0,0.125,0.625,0.22499999403953552,0.5,0.22499999403953552,0.625,0.44999998807907104,0.5,0.44999998807907104,0.625,0.675000011920929,0.5,0.675000011920929,0.625,0.8999999761581421,0.5,0.8999999761581421,0.75,0.22499999403953552,0.75,0.44999998807907104,0.75,0.675000011920929,0.75,0.8999999761581421,0.875,0.22499999403953552,0.875,0.44999998807907104,0.875,0.675000011920929,0.875,0.8999999761581421,1,0.22499999403953552,1,0.44999998807907104,1,0.675000011920929,1,0.8999999761581421,0.125,0.22499999403953552,0,0.22499999403953552,0.125,0.44999998807907104,0,0.44999998807907104,0.125,0.675000011920929,0,0.675000011920929,0.125,0.8999999761581421,0,0.8999999761581421,0.25,0.22499999403953552,0.25,0.44999998807907104,0.25,0.675000011920929,0.25,0.8999999761581421,0.375,0.22499999403953552,0.375,0.44999998807907104,0.375,0.675000011920929,0.375,0.8999999761581421,0.625,0.925000011920929,0.5,0.925000011920929,0.625,0.949999988079071,0.5,0.949999988079071,0.625,0.9750000238418579,0.5,0.9750000238418579,0.75,0.925000011920929,0.75,0.949999988079071,0.75,0.9750000238418579,0.875,0.925000011920929,0.875,0.949999988079071,0.875,0.9750000238418579,1,0.925000011920929,1,0.949999988079071,1,0.9750000238418579,0.125,0.925000011920929,0,0.925000011920929,0.125,0.949999988079071,0,0.949999988079071,0.125,0.9750000238418579,0,0.9750000238418579,0.25,0.925000011920929,0.25,0.949999988079071,0.25,0.9750000238418579,0.375,0.925000011920929,0.375,0.949999988079071,0.375,0.9750000238418579]],\"faces\":[56,0,1,2,0,1,2,0,1,2,3,56,0,2,3,0,2,3,0,1,3,4,56,3,2,4,3,2,4,5,4,3,6,56,3,4,5,3,4,5,5,4,6,7,56,5,4,6,5,4,6,8,7,6,9,56,5,6,7,5,6,7,8,7,9,10,56,7,6,8,7,6,8,11,10,9,12,56,7,8,9,7,8,9,11,10,12,13,56,1,10,11,1,10,11,14,2,15,16,56,1,11,2,1,11,2,14,2,16,3,56,2,11,12,2,11,12,17,3,16,18,56,2,12,4,2,12,4,17,3,18,6,56,4,12,13,4,12,13,19,6,18,20,56,4,13,6,4,13,6,19,6,20,9,56,6,13,14,6,13,14,21,9,20,22,56,6,14,8,6,14,8,21,9,22,12,56,10,15,16,10,15,16,23,15,24,25,56,10,16,11,10,16,11,23,15,25,16,56,11,16,17,11,16,17,26,16,25,27,56,11,17,12,11,17,12,26,16,27,18,56,12,17,18,12,17,18,28,18,27,29,56,12,18,13,12,18,13,28,18,29,20,56,13,18,19,13,18,19,30,20,29,31,56,13,19,14,13,19,14,30,20,31,22,56,15,20,21,15,20,21,32,24,33,34,56,15,21,16,15,21,16,32,24,34,25,56,16,21,22,16,21,22,35,25,34,36,56,16,22,17,16,22,17,35,25,36,27,56,17,22,23,17,22,23,37,27,36,38,56,17,23,18,17,23,18,37,27,38,29,56,18,23,24,18,23,24,39,29,38,40,56,18,24,19,18,24,19,39,29,40,31,56,20,25,26,20,25,26,41,33,42,43,56,20,26,21,20,26,21,41,33,43,34,56,21,26,27,21,26,27,44,34,43,45,56,21,27,22,21,27,22,44,34,45,36,56,22,27,28,22,27,28,46,36,45,47,56,22,28,23,22,28,23,46,36,47,38,56,23,28,29,23,28,29,48,38,47,49,56,23,29,24,23,29,24,48,38,49,40,56,25,30,31,25,30,31,50,42,51,52,56,25,31,26,25,31,26,50,42,52,43,56,26,31,32,26,31,32,53,43,52,54,56,26,32,27,26,32,27,53,43,54,45,56,27,32,33,27,32,33,55,45,54,56,56,27,33,28,27,33,28,55,45,56,47,56,28,33,34,28,33,34,57,47,56,58,56,28,34,29,28,34,29,57,47,58,49,56,30,35,36,30,35,36,59,51,60,61,56,30,36,31,30,36,31,59,51,61,52,56,31,36,37,31,36,37,62,52,61,63,56,31,37,32,31,37,32,62,52,63,54,56,32,37,38,32,37,38,64,54,63,65,56,32,38,33,32,38,33,64,54,65,56,56,33,38,39,33,38,39,66,56,65,67,56,33,39,34,33,39,34,66,56,67,58,56,35,40,41,35,40,41,68,60,69,70,56,35,41,36,35,41,36,68,60,70,61,56,36,41,42,36,41,42,71,61,70,72,56,36,42,37,36,42,37,71,61,72,63,56,37,42,43,37,42,43,73,63,72,74,56,37,43,38,37,43,38,73,63,74,65,56,38,43,44,38,43,44,75,65,74,76,56,38,44,39,38,44,39,75,65,76,67,56,40,45,46,0,1,2,77,69,78,79,56,40,46,41,0,2,3,77,69,79,70,56,41,46,47,3,2,4,80,70,79,81,56,41,47,42,3,4,5,80,70,81,72,56,42,47,48,5,4,6,82,72,81,83,56,42,48,43,5,6,7,82,72,83,74,56,43,48,49,7,6,8,84,74,83,85,56,43,49,44,7,8,9,84,74,85,76,56,45,50,51,1,10,11,86,78,87,88,56,45,51,46,1,11,2,86,78,88,79,56,46,51,52,2,11,12,89,79,88,90,56,46,52,47,2,12,4,89,79,90,81,56,47,52,53,4,12,13,91,81,90,92,56,47,53,48,4,13,6,91,81,92,83,56,48,53,54,6,13,14,93,83,92,94,56,48,54,49,6,14,8,93,83,94,85,56,50,55,56,10,15,16,95,87,96,97,56,50,56,51,10,16,11,95,87,97,88,56,51,56,57,11,16,17,98,88,97,99,56,51,57,52,11,17,12,98,88,99,90,56,52,57,58,12,17,18,100,90,99,101,56,52,58,53,12,18,13,100,90,101,92,56,53,58,59,13,18,19,102,92,101,103,56,53,59,54,13,19,14,102,92,103,94,56,55,60,61,15,20,21,104,96,105,106,56,55,61,56,15,21,16,104,96,106,97,56,56,61,62,16,21,22,107,97,106,108,56,56,62,57,16,22,17,107,97,108,99,56,57,62,63,17,22,23,109,99,108,110,56,57,63,58,17,23,18,109,99,110,101,56,58,63,64,18,23,24,111,101,110,112,56,58,64,59,18,24,19,111,101,112,103,56,60,65,66,20,25,26,113,105,114,115,56,60,66,61,20,26,21,113,105,115,106,56,61,66,67,21,26,27,116,106,115,117,56,61,67,62,21,27,22,116,106,117,108,56,62,67,68,22,27,28,118,108,117,119,56,62,68,63,22,28,23,118,108,119,110,56,63,68,69,23,28,29,120,110,119,121,56,63,69,64,23,29,24,120,110,121,112,56,65,70,71,25,30,31,122,114,123,124,56,65,71,66,25,31,26,122,114,124,115,56,66,71,72,26,31,32,125,115,124,126,56,66,72,67,26,32,27,125,115,126,117,56,67,72,73,27,32,33,127,117,126,128,56,67,73,68,27,33,28,127,117,128,119,56,68,73,74,28,33,34,129,119,128,130,56,68,74,69,28,34,29,129,119,130,121,56,70,75,76,30,35,36,131,123,132,133,56,70,76,71,30,36,31,131,123,133,124,56,71,76,77,31,36,37,134,124,133,135,56,71,77,72,31,37,32,134,124,135,126,56,72,77,78,32,37,38,136,126,135,137,56,72,78,73,32,38,33,136,126,137,128,56,73,78,79,33,38,39,138,128,137,139,56,73,79,74,33,39,34,138,128,139,130,56,75,0,3,35,40,41,140,132,1,4,56,75,3,76,35,41,36,140,132,4,133,56,76,3,5,36,41,42,141,133,4,7,56,76,5,77,36,42,37,141,133,7,135,56,77,5,7,37,42,43,142,135,7,10,56,77,7,78,37,43,38,142,135,10,137,56,78,7,9,38,43,44,143,137,10,13,56,78,9,79,38,44,39,143,137,13,139,56,9,8,80,9,8,45,144,13,12,145,56,9,80,81,9,45,46,144,13,145,146,56,81,80,82,46,45,47,147,146,145,148,56,81,82,83,46,47,48,147,146,148,149,56,83,82,84,48,47,49,150,149,148,151,56,83,84,85,48,49,50,150,149,151,152,56,85,84,86,50,49,51,153,152,151,154,56,85,86,87,50,51,52,153,152,154,155,56,8,14,88,8,14,53,156,12,22,157,56,8,88,80,8,53,45,156,12,157,145,56,80,88,89,45,53,54,158,145,157,159,56,80,89,82,45,54,47,158,145,159,148,56,82,89,90,47,54,55,160,148,159,161,56,82,90,84,47,55,49,160,148,161,151,56,84,90,91,49,55,56,162,151,161,163,56,84,91,86,49,56,51,162,151,163,154,56,14,19,92,14,19,57,164,22,31,165,56,14,92,88,14,57,53,164,22,165,157,56,88,92,93,53,57,58,166,157,165,167,56,88,93,89,53,58,54,166,157,167,159,56,89,93,94,54,58,59,168,159,167,169,56,89,94,90,54,59,55,168,159,169,161,56,90,94,95,55,59,60,170,161,169,171,56,90,95,91,55,60,56,170,161,171,163,56,19,24,96,19,24,61,172,31,40,173,56,19,96,92,19,61,57,172,31,173,165,56,92,96,97,57,61,62,174,165,173,175,56,92,97,93,57,62,58,174,165,175,167,56,93,97,98,58,62,63,176,167,175,177,56,93,98,94,58,63,59,176,167,177,169,56,94,98,99,59,63,64,178,169,177,179,56,94,99,95,59,64,60,178,169,179,171,56,24,29,100,24,29,65,180,40,49,181,56,24,100,96,24,65,61,180,40,181,173,56,96,100,101,61,65,66,182,173,181,183,56,96,101,97,61,66,62,182,173,183,175,56,97,101,102,62,66,67,184,175,183,185,56,97,102,98,62,67,63,184,175,185,177,56,98,102,103,63,67,68,186,177,185,187,56,98,103,99,63,68,64,186,177,187,179,56,29,34,104,29,34,69,188,49,58,189,56,29,104,100,29,69,65,188,49,189,181,56,100,104,105,65,69,70,190,181,189,191,56,100,105,101,65,70,66,190,181,191,183,56,101,105,106,66,70,71,192,183,191,193,56,101,106,102,66,71,67,192,183,193,185,56,102,106,107,67,71,72,194,185,193,195,56,102,107,103,67,72,68,194,185,195,187,56,34,39,108,34,39,73,196,58,67,197,56,34,108,104,34,73,69,196,58,197,189,56,104,108,109,69,73,74,198,189,197,199,56,104,109,105,69,74,70,198,189,199,191,56,105,109,110,70,74,75,200,191,199,201,56,105,110,106,70,75,71,200,191,201,193,56,106,110,111,71,75,76,202,193,201,203,56,106,111,107,71,76,72,202,193,203,195,56,39,44,112,39,44,77,204,67,76,205,56,39,112,108,39,77,73,204,67,205,197,56,108,112,113,73,77,78,206,197,205,207,56,108,113,109,73,78,74,206,197,207,199,56,109,113,114,74,78,79,208,199,207,209,56,109,114,110,74,79,75,208,199,209,201,56,110,114,115,75,79,80,210,201,209,211,56,110,115,111,75,80,76,210,201,211,203,56,44,49,116,9,8,45,212,76,85,213,56,44,116,112,9,45,46,212,76,213,205,56,112,116,117,46,45,47,214,205,213,215,56,112,117,113,46,47,48,214,205,215,207,56,113,117,118,48,47,49,216,207,215,217,56,113,118,114,48,49,50,216,207,217,209,56,114,118,119,50,49,51,218,209,217,219,56,114,119,115,50,51,52,218,209,219,211,56,49,54,120,8,14,53,220,85,94,221,56,49,120,116,8,53,45,220,85,221,213,56,116,120,121,45,53,54,222,213,221,223,56,116,121,117,45,54,47,222,213,223,215,56,117,121,122,47,54,55,224,215,223,225,56,117,122,118,47,55,49,224,215,225,217,56,118,122,123,49,55,56,226,217,225,227,56,118,123,119,49,56,51,226,217,227,219,56,54,59,124,14,19,57,228,94,103,229,56,54,124,120,14,57,53,228,94,229,221,56,120,124,125,53,57,58,230,221,229,231,56,120,125,121,53,58,54,230,221,231,223,56,121,125,126,54,58,59,232,223,231,233,56,121,126,122,54,59,55,232,223,233,225,56,122,126,127,55,59,60,234,225,233,235,56,122,127,123,55,60,56,234,225,235,227,56,59,64,128,19,24,61,236,103,112,237,56,59,128,124,19,61,57,236,103,237,229,56,124,128,129,57,61,62,238,229,237,239,56,124,129,125,57,62,58,238,229,239,231,56,125,129,130,58,62,63,240,231,239,241,56,125,130,126,58,63,59,240,231,241,233,56,126,130,131,59,63,64,242,233,241,243,56,126,131,127,59,64,60,242,233,243,235,56,64,69,132,24,29,65,244,112,121,245,56,64,132,128,24,65,61,244,112,245,237,56,128,132,133,61,65,66,246,237,245,247,56,128,133,129,61,66,62,246,237,247,239,56,129,133,134,62,66,67,248,239,247,249,56,129,134,130,62,67,63,248,239,249,241,56,130,134,135,63,67,68,250,241,249,251,56,130,135,131,63,68,64,250,241,251,243,56,69,74,136,29,34,69,252,121,130,253,56,69,136,132,29,69,65,252,121,253,245,56,132,136,137,65,69,70,254,245,253,255,56,132,137,133,65,70,66,254,245,255,247,56,133,137,138,66,70,71,256,247,255,257,56,133,138,134,66,71,67,256,247,257,249,56,134,138,139,67,71,72,258,249,257,259,56,134,139,135,67,72,68,258,249,259,251,56,74,79,140,34,39,73,260,130,139,261,56,74,140,136,34,73,69,260,130,261,253,56,136,140,141,69,73,74,262,253,261,263,56,136,141,137,69,74,70,262,253,263,255,56,137,141,142,70,74,75,264,255,263,265,56,137,142,138,70,75,71,264,255,265,257,56,138,142,143,71,75,76,266,257,265,267,56,138,143,139,71,76,72,266,257,267,259,56,79,9,81,39,44,77,268,139,13,146,56,79,81,140,39,77,73,268,139,146,261,56,140,81,83,73,77,78,269,261,146,149,56,140,83,141,73,78,74,269,261,149,263,56,141,83,85,74,78,79,270,263,149,152,56,141,85,142,74,79,75,270,263,152,265,56,142,85,87,75,79,80,271,265,152,155,56,142,87,143,75,80,76,271,265,155,267,56,87,86,144,52,51,81,272,155,154,273,56,87,144,145,52,81,82,272,155,273,274,56,145,144,146,82,81,83,275,274,273,276,56,145,146,147,82,83,84,275,274,276,277,56,147,146,148,84,83,85,278,277,276,279,56,147,148,149,84,85,86,278,277,279,280,56,149,148,150,86,85,87,281,280,279,282,56,149,150,151,86,87,88,281,280,282,283,56,86,91,152,51,56,89,284,154,163,285,56,86,152,144,51,89,81,284,154,285,273,56,144,152,153,81,89,90,286,273,285,287,56,144,153,146,81,90,83,286,273,287,276,56,146,153,154,83,90,91,288,276,287,289,56,146,154,148,83,91,85,288,276,289,279,56,148,154,155,85,91,92,290,279,289,291,56,148,155,150,85,92,87,290,279,291,282,56,91,95,156,56,60,93,292,163,171,293,56,91,156,152,56,93,89,292,163,293,285,56,152,156,157,89,93,94,294,285,293,295,56,152,157,153,89,94,90,294,285,295,287,56,153,157,158,90,94,95,296,287,295,297,56,153,158,154,90,95,91,296,287,297,289,56,154,158,159,91,95,96,298,289,297,299,56,154,159,155,91,96,92,298,289,299,291,56,95,99,160,60,64,97,300,171,179,301,56,95,160,156,60,97,93,300,171,301,293,56,156,160,161,93,97,98,302,293,301,303,56,156,161,157,93,98,94,302,293,303,295,56,157,161,162,94,98,99,304,295,303,305,56,157,162,158,94,99,95,304,295,305,297,56,158,162,163,95,99,100,306,297,305,307,56,158,163,159,95,100,96,306,297,307,299,56,99,103,164,64,68,101,308,179,187,309,56,99,164,160,64,101,97,308,179,309,301,56,160,164,165,97,101,102,310,301,309,311,56,160,165,161,97,102,98,310,301,311,303,56,161,165,166,98,102,103,312,303,311,313,56,161,166,162,98,103,99,312,303,313,305,56,162,166,167,99,103,104,314,305,313,315,56,162,167,163,99,104,100,314,305,315,307,56,103,107,168,68,72,105,316,187,195,317,56,103,168,164,68,105,101,316,187,317,309,56,164,168,169,101,105,106,318,309,317,319,56,164,169,165,101,106,102,318,309,319,311,56,165,169,170,102,106,107,320,311,319,321,56,165,170,166,102,107,103,320,311,321,313,56,166,170,171,103,107,108,322,313,321,323,56,166,171,167,103,108,104,322,313,323,315,56,107,111,172,72,76,109,324,195,203,325,56,107,172,168,72,109,105,324,195,325,317,56,168,172,173,105,109,110,326,317,325,327,56,168,173,169,105,110,106,326,317,327,319,56,169,173,174,106,110,111,328,319,327,329,56,169,174,170,106,111,107,328,319,329,321,56,170,174,175,107,111,112,330,321,329,331,56,170,175,171,107,112,108,330,321,331,323,56,111,115,176,76,80,113,332,203,211,333,56,111,176,172,76,113,109,332,203,333,325,56,172,176,177,109,113,114,334,325,333,335,56,172,177,173,109,114,110,334,325,335,327,56,173,177,178,110,114,115,336,327,335,337,56,173,178,174,110,115,111,336,327,337,329,56,174,178,179,111,115,116,338,329,337,339,56,174,179,175,111,116,112,338,329,339,331,56,115,119,180,52,51,81,340,211,219,341,56,115,180,176,52,81,82,340,211,341,333,56,176,180,181,82,81,83,342,333,341,343,56,176,181,177,82,83,84,342,333,343,335,56,177,181,182,84,83,85,344,335,343,345,56,177,182,178,84,85,86,344,335,345,337,56,178,182,183,86,85,87,346,337,345,347,56,178,183,179,86,87,88,346,337,347,339,56,119,123,184,51,56,89,348,219,227,349,56,119,184,180,51,89,81,348,219,349,341,56,180,184,185,81,89,90,350,341,349,351,56,180,185,181,81,90,83,350,341,351,343,56,181,185,186,83,90,91,352,343,351,353,56,181,186,182,83,91,85,352,343,353,345,56,182,186,187,85,91,92,354,345,353,355,56,182,187,183,85,92,87,354,345,355,347,56,123,127,188,56,60,93,356,227,235,357,56,123,188,184,56,93,89,356,227,357,349,56,184,188,189,89,93,94,358,349,357,359,56,184,189,185,89,94,90,358,349,359,351,56,185,189,190,90,94,95,360,351,359,361,56,185,190,186,90,95,91,360,351,361,353,56,186,190,191,91,95,96,362,353,361,363,56,186,191,187,91,96,92,362,353,363,355,56,127,131,192,60,64,97,364,235,243,365,56,127,192,188,60,97,93,364,235,365,357,56,188,192,193,93,97,98,366,357,365,367,56,188,193,189,93,98,94,366,357,367,359,56,189,193,194,94,98,99,368,359,367,369,56,189,194,190,94,99,95,368,359,369,361,56,190,194,195,95,99,100,370,361,369,371,56,190,195,191,95,100,96,370,361,371,363,56,131,135,196,64,68,101,372,243,251,373,56,131,196,192,64,101,97,372,243,373,365,56,192,196,197,97,101,102,374,365,373,375,56,192,197,193,97,102,98,374,365,375,367,56,193,197,198,98,102,103,376,367,375,377,56,193,198,194,98,103,99,376,367,377,369,56,194,198,199,99,103,104,378,369,377,379,56,194,199,195,99,104,100,378,369,379,371,56,135,139,200,68,72,105,380,251,259,381,56,135,200,196,68,105,101,380,251,381,373,56,196,200,201,101,105,106,382,373,381,383,56,196,201,197,101,106,102,382,373,383,375,56,197,201,202,102,106,107,384,375,383,385,56,197,202,198,102,107,103,384,375,385,377,56,198,202,203,103,107,108,386,377,385,387,56,198,203,199,103,108,104,386,377,387,379,56,139,143,204,72,76,109,388,259,267,389,56,139,204,200,72,109,105,388,259,389,381,56,200,204,205,105,109,110,390,381,389,391,56,200,205,201,105,110,106,390,381,391,383,56,201,205,206,106,110,111,392,383,391,393,56,201,206,202,106,111,107,392,383,393,385,56,202,206,207,107,111,112,394,385,393,395,56,202,207,203,107,112,108,394,385,395,387,56,143,87,145,76,80,113,396,267,155,274,56,143,145,204,76,113,109,396,267,274,389,56,204,145,147,109,113,114,397,389,274,277,56,204,147,205,109,114,110,397,389,277,391,56,205,147,149,110,114,115,398,391,277,280,56,205,149,206,110,115,111,398,391,280,393,56,206,149,151,111,115,116,399,393,280,283,56,206,151,207,111,116,112,399,393,283,395,56,151,150,208,88,87,117,400,283,282,401,56,151,208,209,88,117,118,400,283,401,402,56,209,208,210,118,117,119,403,402,401,404,56,209,210,211,118,119,120,403,402,404,405,56,211,210,212,120,119,121,406,405,404,407,56,211,212,213,120,121,122,406,405,407,408,56,213,212,214,122,121,123,409,408,407,410,56,150,155,215,87,92,124,411,282,291,412,56,150,215,208,87,124,117,411,282,412,401,56,208,215,216,117,124,125,413,401,412,414,56,208,216,210,117,125,119,413,401,414,404,56,210,216,217,119,125,126,415,404,414,416,56,210,217,212,119,126,121,415,404,416,407,56,212,217,214,121,126,127,417,407,416,410,56,155,159,218,92,96,128,418,291,299,419,56,155,218,215,92,128,124,418,291,419,412,56,215,218,219,124,128,129,420,412,419,421,56,215,219,216,124,129,125,420,412,421,414,56,216,219,220,125,129,130,422,414,421,423,56,216,220,217,125,130,126,422,414,423,416,56,217,220,214,126,130,131,424,416,423,410,56,159,163,221,96,100,132,425,299,307,426,56,159,221,218,96,132,128,425,299,426,419,56,218,221,222,128,132,133,427,419,426,428,56,218,222,219,128,133,129,427,419,428,421,56,219,222,223,129,133,134,429,421,428,430,56,219,223,220,129,134,130,429,421,430,423,56,220,223,214,130,134,135,431,423,430,410,56,163,167,224,100,104,136,432,307,315,433,56,163,224,221,100,136,132,432,307,433,426,56,221,224,225,132,136,137,434,426,433,435,56,221,225,222,132,137,133,434,426,435,428,56,222,225,226,133,137,138,436,428,435,437,56,222,226,223,133,138,134,436,428,437,430,56,223,226,214,134,138,139,438,430,437,410,56,167,171,227,104,108,140,439,315,323,440,56,167,227,224,104,140,136,439,315,440,433,56,224,227,228,136,140,141,441,433,440,442,56,224,228,225,136,141,137,441,433,442,435,56,225,228,229,137,141,142,443,435,442,444,56,225,229,226,137,142,138,443,435,444,437,56,226,229,214,138,142,143,445,437,444,410,56,171,175,230,108,112,144,446,323,331,447,56,171,230,227,108,144,140,446,323,447,440,56,227,230,231,140,144,145,448,440,447,449,56,227,231,228,140,145,141,448,440,449,442,56,228,231,232,141,145,146,450,442,449,451,56,228,232,229,141,146,142,450,442,451,444,56,229,232,214,142,146,147,452,444,451,410,56,175,179,233,112,116,148,453,331,339,454,56,175,233,230,112,148,144,453,331,454,447,56,230,233,234,144,148,149,455,447,454,456,56,230,234,231,144,149,145,455,447,456,449,56,231,234,235,145,149,150,457,449,456,458,56,231,235,232,145,150,146,457,449,458,451,56,232,235,214,146,150,151,459,451,458,410,56,179,183,236,88,87,117,460,339,347,461,56,179,236,233,88,117,118,460,339,461,454,56,233,236,237,118,117,119,462,454,461,463,56,233,237,234,118,119,120,462,454,463,456,56,234,237,238,120,119,121,464,456,463,465,56,234,238,235,120,121,122,464,456,465,458,56,235,238,214,122,121,123,466,458,465,410,56,183,187,239,87,92,124,467,347,355,468,56,183,239,236,87,124,117,467,347,468,461,56,236,239,240,117,124,125,469,461,468,470,56,236,240,237,117,125,119,469,461,470,463,56,237,240,241,119,125,126,471,463,470,472,56,237,241,238,119,126,121,471,463,472,465,56,238,241,214,121,126,127,473,465,472,410,56,187,191,242,92,96,128,474,355,363,475,56,187,242,239,92,128,124,474,355,475,468,56,239,242,243,124,128,129,476,468,475,477,56,239,243,240,124,129,125,476,468,477,470,56,240,243,244,125,129,130,478,470,477,479,56,240,244,241,125,130,126,478,470,479,472,56,241,244,214,126,130,131,480,472,479,410,56,191,195,245,96,100,132,481,363,371,482,56,191,245,242,96,132,128,481,363,482,475,56,242,245,246,128,132,133,483,475,482,484,56,242,246,243,128,133,129,483,475,484,477,56,243,246,247,129,133,134,485,477,484,486,56,243,247,244,129,134,130,485,477,486,479,56,244,247,214,130,134,135,487,479,486,410,56,195,199,248,100,104,136,488,371,379,489,56,195,248,245,100,136,132,488,371,489,482,56,245,248,249,132,136,137,490,482,489,491,56,245,249,246,132,137,133,490,482,491,484,56,246,249,250,133,137,138,492,484,491,493,56,246,250,247,133,138,134,492,484,493,486,56,247,250,214,134,138,139,494,486,493,410,56,199,203,251,104,108,140,495,379,387,496,56,199,251,248,104,140,136,495,379,496,489,56,248,251,252,136,140,141,497,489,496,498,56,248,252,249,136,141,137,497,489,498,491,56,249,252,253,137,141,142,499,491,498,500,56,249,253,250,137,142,138,499,491,500,493,56,250,253,214,138,142,143,501,493,500,410,56,203,207,254,108,112,144,502,387,395,503,56,203,254,251,108,144,140,502,387,503,496,56,251,254,255,140,144,145,504,496,503,505,56,251,255,252,140,145,141,504,496,505,498,56,252,255,256,141,145,146,506,498,505,507,56,252,256,253,141,146,142,506,498,507,500,56,253,256,214,142,146,147,508,500,507,410,56,207,151,209,112,116,148,509,395,283,402,56,207,209,254,112,148,144,509,395,402,503,56,254,209,211,144,148,149,510,503,402,405,56,254,211,255,144,149,145,510,503,405,505,56,255,211,213,145,149,150,511,505,405,408,56,255,213,256,145,150,146,511,505,408,507,56,256,213,214,146,150,151,512,507,408,410,56,257,258,259,64,152,153,513,514,515,516,56,257,259,260,64,153,154,513,514,516,517,56,260,259,261,154,153,155,518,517,516,519,56,260,261,262,154,155,156,518,517,519,520,56,262,261,263,156,155,157,521,520,519,522,56,262,263,264,156,157,158,521,520,522,523,56,264,263,265,158,157,159,524,523,522,525,56,264,265,266,158,159,160,524,523,525,526,56,258,267,268,152,68,161,527,515,528,529,56,258,268,259,152,161,153,527,515,529,516,56,259,268,269,153,161,162,530,516,529,531,56,259,269,261,153,162,155,530,516,531,519,56,261,269,270,155,162,163,532,519,531,533,56,261,270,263,155,163,157,532,519,533,522,56,263,270,271,157,163,164,534,522,533,535,56,263,271,265,157,164,159,534,522,535,525,56,267,272,273,68,165,166,536,528,537,538,56,267,273,268,68,166,161,536,528,538,529,56,268,273,274,161,166,167,539,529,538,540,56,268,274,269,161,167,162,539,529,540,531,56,269,274,275,162,167,168,541,531,540,542,56,269,275,270,162,168,163,541,531,542,533,56,270,275,276,163,168,169,543,533,542,544,56,270,276,271,163,169,164,543,533,544,535,56,272,277,278,165,72,170,545,537,546,547,56,272,278,273,165,170,166,545,537,547,538,56,273,278,279,166,170,171,548,538,547,549,56,273,279,274,166,171,167,548,538,549,540,56,274,279,280,167,171,172,550,540,549,551,56,274,280,275,167,172,168,550,540,551,542,56,275,280,281,168,172,173,552,542,551,553,56,275,281,276,168,173,169,552,542,553,544,56,277,282,283,72,174,175,554,546,555,556,56,277,283,278,72,175,170,554,546,556,547,56,278,283,284,170,175,176,557,547,556,558,56,278,284,279,170,176,171,557,547,558,549,56,279,284,285,171,176,177,559,549,558,560,56,279,285,280,171,177,172,559,549,560,551,56,280,285,286,172,177,178,561,551,560,562,56,280,286,281,172,178,173,561,551,562,553,56,282,287,288,174,76,179,563,555,564,565,56,282,288,283,174,179,175,563,555,565,556,56,283,288,289,175,179,180,566,556,565,567,56,283,289,284,175,180,176,566,556,567,558,56,284,289,290,176,180,181,568,558,567,569,56,284,290,285,176,181,177,568,558,569,560,56,285,290,291,177,181,182,570,560,569,571,56,285,291,286,177,182,178,570,560,571,562,56,287,292,293,76,183,184,572,564,573,574,56,287,293,288,76,184,179,572,564,574,565,56,288,293,294,179,184,185,575,565,574,576,56,288,294,289,179,185,180,575,565,576,567,56,289,294,295,180,185,186,577,567,576,578,56,289,295,290,180,186,181,577,567,578,569,56,290,295,296,181,186,187,579,569,578,580,56,290,296,291,181,187,182,579,569,580,571,56,292,257,260,183,80,188,581,573,514,517,56,292,260,293,183,188,184,581,573,517,574,56,293,260,262,184,188,189,582,574,517,520,56,293,262,294,184,189,185,582,574,520,576,56,294,262,264,185,189,190,583,576,520,523,56,294,264,295,185,190,186,583,576,523,578,56,295,264,266,186,190,191,584,578,523,526,56,295,266,296,186,191,187,584,578,526,580,56,266,265,297,160,159,192,585,526,525,586,56,266,297,298,160,192,193,585,526,586,587,56,298,297,299,193,192,194,588,587,586,589,56,298,299,300,193,194,195,588,587,589,590,56,300,299,301,195,194,196,591,590,589,592,56,300,301,302,195,196,197,591,590,592,593,56,302,301,303,197,196,198,594,593,592,595,56,302,303,115,197,198,135,594,593,595,596,56,265,271,304,159,164,199,597,525,535,598,56,265,304,297,159,199,192,597,525,598,586,56,297,304,305,192,199,200,599,586,598,600,56,297,305,299,192,200,194,599,586,600,589,56,299,305,306,194,200,201,601,589,600,602,56,299,306,301,194,201,196,601,589,602,592,56,301,306,307,196,201,139,603,592,602,604,56,301,307,303,196,139,198,603,592,604,595,56,271,276,308,164,169,202,605,535,544,606,56,271,308,304,164,202,199,605,535,606,598,56,304,308,309,199,202,203,607,598,606,608,56,304,309,305,199,203,200,607,598,608,600,56,305,309,310,200,203,204,609,600,608,610,56,305,310,306,200,204,201,609,600,610,602,56,306,310,311,201,204,205,611,602,610,612,56,306,311,307,201,205,139,611,602,612,604,56,276,281,312,169,173,206,613,544,553,614,56,276,312,308,169,206,202,613,544,614,606,56,308,312,313,202,206,207,615,606,614,616,56,308,313,309,202,207,203,615,606,616,608,56,309,313,314,203,207,208,617,608,616,618,56,309,314,310,203,208,204,617,608,618,610,56,310,314,315,204,208,143,619,610,618,620,56,310,315,311,204,143,205,619,610,620,612,56,281,286,316,173,178,209,621,553,562,622,56,281,316,312,173,209,206,621,553,622,614,56,312,316,317,206,209,210,623,614,622,624,56,312,317,313,206,210,207,623,614,624,616,56,313,317,318,207,210,211,625,616,624,626,56,313,318,314,207,211,208,625,616,626,618,56,314,318,319,208,211,212,627,618,626,628,56,314,319,315,208,212,143,627,618,628,620,56,286,291,320,178,182,213,629,562,571,630,56,286,320,316,178,213,209,629,562,630,622,56,316,320,321,209,213,214,631,622,630,632,56,316,321,317,209,214,210,631,622,632,624,56,317,321,322,210,214,215,633,624,632,634,56,317,322,318,210,215,211,633,624,634,626,56,318,322,323,211,215,147,635,626,634,636,56,318,323,319,211,147,212,635,626,636,628,56,291,296,324,182,187,216,637,571,580,638,56,291,324,320,182,216,213,637,571,638,630,56,320,324,325,213,216,217,639,630,638,640,56,320,325,321,213,217,214,639,630,640,632,56,321,325,326,214,217,218,641,632,640,642,56,321,326,322,214,218,215,641,632,642,634,56,322,326,327,215,218,219,643,634,642,644,56,322,327,323,215,219,147,643,634,644,636,56,296,266,298,187,191,220,645,580,526,587,56,296,298,324,187,220,216,645,580,587,638,56,324,298,300,216,220,221,646,638,587,590,56,324,300,325,216,221,217,646,638,590,640,56,325,300,302,217,221,222,647,640,590,593,56,325,302,326,217,222,218,647,640,593,642,56,326,302,115,218,222,151,648,642,593,596,56,326,115,327,218,151,219,648,642,596,644,56,328,329,330,143,205,223,649,650,651,652,56,328,330,331,143,223,224,649,650,652,653,56,331,330,332,224,223,225,654,653,652,655,56,331,332,333,224,225,226,654,653,655,656,56,333,332,334,226,225,227,657,656,655,658,56,333,334,335,226,227,228,657,656,658,659,56,335,334,336,228,227,229,660,659,658,661,56,335,336,337,228,229,230,660,659,661,662,56,329,338,339,205,139,231,663,651,664,665,56,329,339,330,205,231,223,663,651,665,652,56,330,339,340,223,231,232,666,652,665,667,56,330,340,332,223,232,225,666,652,667,655,56,332,340,341,225,232,233,668,655,667,669,56,332,341,334,225,233,227,668,655,669,658,56,334,341,342,227,233,234,670,658,669,671,56,334,342,336,227,234,229,670,658,671,661,56,338,343,344,139,198,235,672,664,673,674,56,338,344,339,139,235,231,672,664,674,665,56,339,344,345,231,235,236,675,665,674,676,56,339,345,340,231,236,232,675,665,676,667,56,340,345,346,232,236,237,677,667,676,678,56,340,346,341,232,237,233,677,667,678,669,56,341,346,347,233,237,238,679,669,678,680,56,341,347,342,233,238,234,679,669,680,671,56,343,348,349,198,135,239,681,673,682,683,56,343,349,344,198,239,235,681,673,683,674,56,344,349,350,235,239,240,684,674,683,685,56,344,350,345,235,240,236,684,674,685,676,56,345,350,351,236,240,241,686,676,685,687,56,345,351,346,236,241,237,686,676,687,678,56,346,351,352,237,241,242,688,678,687,689,56,346,352,347,237,242,238,688,678,689,680,56,348,353,354,151,219,243,690,682,691,692,56,348,354,349,151,243,244,690,682,692,683,56,349,354,355,244,243,245,693,683,692,694,56,349,355,350,244,245,246,693,683,694,685,56,350,355,356,246,245,247,695,685,694,696,56,350,356,351,246,247,248,695,685,696,687,56,351,356,357,248,247,249,697,687,696,698,56,351,357,352,248,249,250,697,687,698,689,56,353,358,359,219,147,251,699,691,700,701,56,353,359,354,219,251,243,699,691,701,692,56,354,359,360,243,251,252,702,692,701,703,56,354,360,355,243,252,245,702,692,703,694,56,355,360,361,245,252,253,704,694,703,705,56,355,361,356,245,253,247,704,694,705,696,56,356,361,362,247,253,254,706,696,705,707,56,356,362,357,247,254,249,706,696,707,698,56,358,363,364,147,212,255,708,700,709,710,56,358,364,359,147,255,251,708,700,710,701,56,359,364,365,251,255,256,711,701,710,712,56,359,365,360,251,256,252,711,701,712,703,56,360,365,366,252,256,257,713,703,712,714,56,360,366,361,252,257,253,713,703,714,705,56,361,366,367,253,257,258,715,705,714,716,56,361,367,362,253,258,254,715,705,716,707,56,363,328,331,212,143,224,717,709,650,653,56,363,331,364,212,224,255,717,709,653,710,56,364,331,333,255,224,226,718,710,653,656,56,364,333,365,255,226,256,718,710,656,712,56,365,333,335,256,226,228,719,712,656,659,56,365,335,366,256,228,257,719,712,659,714,56,366,335,337,257,228,230,720,714,659,662,56,366,337,367,257,230,258,720,714,662,716,56,337,336,368,230,229,259,721,662,661,722,56,337,368,369,230,259,260,721,662,722,723,56,369,368,370,260,259,261,724,723,722,725,56,369,370,371,260,261,262,724,723,725,726,56,371,370,372,262,261,263,727,726,725,728,56,371,372,373,262,263,264,727,726,728,729,56,373,372,374,264,263,165,730,729,728,731,56,373,374,375,264,165,72,730,729,731,732,56,336,342,376,229,234,265,733,661,671,734,56,336,376,368,229,265,259,733,661,734,722,56,368,376,377,259,265,266,735,722,734,736,56,368,377,370,259,266,261,735,722,736,725,56,370,377,378,261,266,267,737,725,736,738,56,370,378,372,261,267,263,737,725,738,728,56,372,378,379,263,267,68,739,728,738,740,56,372,379,374,263,68,165,739,728,740,731,56,342,347,380,234,238,268,741,671,680,742,56,342,380,376,234,268,265,741,671,742,734,56,376,380,381,265,268,269,743,734,742,744,56,376,381,377,265,269,266,743,734,744,736,56,377,381,382,266,269,270,745,736,744,746,56,377,382,378,266,270,267,745,736,746,738,56,378,382,383,267,270,152,747,738,746,748,56,378,383,379,267,152,68,747,738,748,740,56,347,352,384,238,242,271,749,680,689,750,56,347,384,380,238,271,268,749,680,750,742,56,380,384,385,268,271,272,751,742,750,752,56,380,385,381,268,272,269,751,742,752,744,56,381,385,386,269,272,273,753,744,752,754,56,381,386,382,269,273,270,753,744,754,746,56,382,386,387,270,273,64,755,746,754,756,56,382,387,383,270,64,152,755,746,756,748,56,352,357,388,250,249,274,757,689,698,758,56,352,388,384,250,274,275,757,689,758,750,56,384,388,389,275,274,276,759,750,758,760,56,384,389,385,275,276,277,759,750,760,752,56,385,389,390,277,276,278,761,752,760,762,56,385,390,386,277,278,279,761,752,762,754,56,386,390,391,279,278,183,763,754,762,764,56,386,391,387,279,183,80,763,754,764,756,56,357,362,392,249,254,280,765,698,707,766,56,357,392,388,249,280,274,765,698,766,758,56,388,392,393,274,280,281,767,758,766,768,56,388,393,389,274,281,276,767,758,768,760,56,389,393,394,276,281,282,769,760,768,770,56,389,394,390,276,282,278,769,760,770,762,56,390,394,395,278,282,76,771,762,770,772,56,390,395,391,278,76,183,771,762,772,764,56,362,367,396,254,258,283,773,707,716,774,56,362,396,392,254,283,280,773,707,774,766,56,392,396,397,280,283,284,775,766,774,776,56,392,397,393,280,284,281,775,766,776,768,56,393,397,398,281,284,285,777,768,776,778,56,393,398,394,281,285,282,777,768,778,770,56,394,398,399,282,285,174,779,770,778,780,56,394,399,395,282,174,76,779,770,780,772,56,367,337,369,258,230,260,781,716,662,723,56,367,369,396,258,260,283,781,716,723,774,56,396,369,371,283,260,262,782,774,723,726,56,396,371,397,283,262,284,782,774,726,776,56,397,371,373,284,262,264,783,776,726,729,56,397,373,398,284,264,285,783,776,729,778,56,398,373,375,285,264,72,784,778,729,732,56,398,375,399,285,72,174,784,778,732,780,56,400,401,402,155,156,64,785,786,787,788,56,401,400,403,156,155,159,789,787,786,790,56,401,403,404,156,159,160,789,787,790,791,56,404,403,405,160,159,194,792,791,790,793,56,404,405,406,160,194,195,792,791,793,794,56,406,405,407,195,194,198,795,794,793,796,56,406,407,408,195,198,135,795,794,796,797,56,409,400,402,162,155,152,798,799,786,788,56,400,409,410,155,162,164,800,786,799,801,56,400,410,403,155,164,159,800,786,801,790,56,403,410,411,159,164,200,802,790,801,803,56,403,411,405,159,200,194,802,790,803,793,56,405,411,412,194,200,139,804,793,803,805,56,405,412,407,194,139,198,804,793,805,796,56,413,409,402,167,162,68,806,807,799,788,56,409,413,414,162,167,169,808,799,807,809,56,409,414,410,162,169,164,808,799,809,801,56,410,414,415,164,169,203,810,801,809,811,56,410,415,411,164,203,200,810,801,811,803,56,411,415,416,200,203,205,812,803,811,813,56,411,416,412,200,205,139,812,803,813,805,56,417,413,402,171,167,165,814,815,807,788,56,413,417,418,167,171,173,816,807,815,817,56,413,418,414,167,173,169,816,807,817,809,56,414,418,419,169,173,207,818,809,817,819,56,414,419,415,169,207,203,818,809,819,811,56,415,419,420,203,207,143,820,811,819,821,56,415,420,416,203,143,205,820,811,821,813,56,421,417,402,176,171,72,822,823,815,788,56,417,421,422,171,176,178,824,815,823,825,56,417,422,418,171,178,173,824,815,825,817,56,418,422,423,173,178,210,826,817,825,827,56,418,423,419,173,210,207,826,817,827,819,56,419,423,424,207,210,212,828,819,827,829,56,419,424,420,207,212,143,828,819,829,821,56,425,421,402,180,176,174,830,831,823,788,56,421,425,426,176,180,182,832,823,831,833,56,421,426,422,176,182,178,832,823,833,825,56,422,426,427,178,182,214,834,825,833,835,56,422,427,423,178,214,210,834,825,835,827,56,423,427,428,210,214,147,836,827,835,837,56,423,428,424,210,147,212,836,827,837,829,56,429,425,402,185,180,76,838,839,831,788,56,425,429,430,180,185,187,840,831,839,841,56,425,430,426,180,187,182,840,831,841,833,56,426,430,431,182,187,217,842,833,841,843,56,426,431,427,182,217,214,842,833,843,835,56,427,431,432,214,217,219,844,835,843,845,56,427,432,428,214,219,147,844,835,845,837,56,433,429,402,189,185,183,846,847,839,788,56,429,433,434,185,189,191,848,839,847,849,56,429,434,430,185,191,187,848,839,849,841,56,430,434,435,187,191,221,850,841,849,851,56,430,435,431,187,221,217,850,841,851,843,56,431,435,436,217,221,151,852,843,851,853,56,431,436,432,217,151,219,852,843,853,845,56,437,433,402,155,156,64,854,855,847,788,56,433,437,438,156,155,159,856,847,855,857,56,433,438,434,156,159,160,856,847,857,849,56,434,438,439,160,159,194,858,849,857,859,56,434,439,435,160,194,195,858,849,859,851,56,435,439,440,195,194,198,860,851,859,861,56,435,440,436,195,198,135,860,851,861,853,56,441,437,402,162,155,152,862,863,855,788,56,437,441,442,155,162,164,864,855,863,865,56,437,442,438,155,164,159,864,855,865,857,56,438,442,443,159,164,200,866,857,865,867,56,438,443,439,159,200,194,866,857,867,859,56,439,443,444,194,200,139,868,859,867,869,56,439,444,440,194,139,198,868,859,869,861,56,445,441,402,167,162,68,870,871,863,788,56,441,445,446,162,167,169,872,863,871,873,56,441,446,442,162,169,164,872,863,873,865,56,442,446,447,164,169,203,874,865,873,875,56,442,447,443,164,203,200,874,865,875,867,56,443,447,448,200,203,205,876,867,875,877,56,443,448,444,200,205,139,876,867,877,869,56,449,445,402,171,167,165,878,879,871,788,56,445,449,450,167,171,173,880,871,879,881,56,445,450,446,167,173,169,880,871,881,873,56,446,450,451,169,173,207,882,873,881,883,56,446,451,447,169,207,203,882,873,883,875,56,447,451,452,203,207,143,884,875,883,885,56,447,452,448,203,143,205,884,875,885,877,56,453,449,402,176,171,72,886,887,879,788,56,449,453,454,171,176,178,888,879,887,889,56,449,454,450,171,178,173,888,879,889,881,56,450,454,455,173,178,210,890,881,889,891,56,450,455,451,173,210,207,890,881,891,883,56,451,455,456,207,210,212,892,883,891,893,56,451,456,452,207,212,143,892,883,893,885,56,457,453,402,180,176,174,894,895,887,788,56,453,457,458,176,180,182,896,887,895,897,56,453,458,454,176,182,178,896,887,897,889,56,454,458,459,178,182,214,898,889,897,899,56,454,459,455,178,214,210,898,889,899,891,56,455,459,460,210,214,147,900,891,899,901,56,455,460,456,210,147,212,900,891,901,893,56,461,457,402,185,180,76,902,903,895,788,56,457,461,462,180,185,187,904,895,903,905,56,457,462,458,180,187,182,904,895,905,897,56,458,462,463,182,187,217,906,897,905,907,56,458,463,459,182,217,214,906,897,907,899,56,459,463,464,214,217,219,908,899,907,909,56,459,464,460,214,219,147,908,899,909,901,56,401,461,402,189,185,183,910,787,903,788,56,461,401,404,185,189,191,911,903,787,791,56,461,404,462,185,191,187,911,903,791,905,56,462,404,406,187,191,221,912,905,791,794,56,462,406,463,187,221,217,912,905,794,907,56,463,406,408,217,221,151,913,907,794,797,56,463,408,464,217,151,219,913,907,797,909,56,408,407,465,64,152,155,914,797,796,915,56,408,465,466,64,155,156,914,797,915,916,56,466,465,467,156,155,159,917,916,915,918,56,466,467,468,156,159,160,917,916,918,919,56,468,467,469,160,159,194,920,919,918,921,56,468,469,470,160,194,195,920,919,921,922,56,470,469,471,195,194,198,923,922,921,924,56,470,471,472,195,198,135,923,922,924,925,56,407,412,473,152,68,162,926,796,805,927,56,407,473,465,152,162,155,926,796,927,915,56,465,473,474,155,162,164,928,915,927,929,56,465,474,467,155,164,159,928,915,929,918,56,467,474,475,159,164,200,930,918,929,931,56,467,475,469,159,200,194,930,918,931,921,56,469,475,476,194,200,139,932,921,931,933,56,469,476,471,194,139,198,932,921,933,924,56,412,416,477,68,165,167,934,805,813,935,56,412,477,473,68,167,162,934,805,935,927,56,473,477,478,162,167,169,936,927,935,937,56,473,478,474,162,169,164,936,927,937,929,56,474,478,479,164,169,203,938,929,937,939,56,474,479,475,164,203,200,938,929,939,931,56,475,479,480,200,203,205,940,931,939,941,56,475,480,476,200,205,139,940,931,941,933,56,416,420,481,165,72,171,942,813,821,943,56,416,481,477,165,171,167,942,813,943,935,56,477,481,482,167,171,173,944,935,943,945,56,477,482,478,167,173,169,944,935,945,937,56,478,482,483,169,173,207,946,937,945,947,56,478,483,479,169,207,203,946,937,947,939,56,479,483,484,203,207,143,948,939,947,949,56,479,484,480,203,143,205,948,939,949,941,56,420,424,485,72,174,176,950,821,829,951,56,420,485,481,72,176,171,950,821,951,943,56,481,485,486,171,176,178,952,943,951,953,56,481,486,482,171,178,173,952,943,953,945,56,482,486,487,173,178,210,954,945,953,955,56,482,487,483,173,210,207,954,945,955,947,56,483,487,488,207,210,212,956,947,955,957,56,483,488,484,207,212,143,956,947,957,949,56,424,428,489,174,76,180,958,829,837,959,56,424,489,485,174,180,176,958,829,959,951,56,485,489,490,176,180,182,960,951,959,961,56,485,490,486,176,182,178,960,951,961,953,56,486,490,491,178,182,214,962,953,961,963,56,486,491,487,178,214,210,962,953,963,955,56,487,491,492,210,214,147,964,955,963,965,56,487,492,488,210,147,212,964,955,965,957,56,428,432,493,76,183,185,966,837,845,967,56,428,493,489,76,185,180,966,837,967,959,56,489,493,494,180,185,187,968,959,967,969,56,489,494,490,180,187,182,968,959,969,961,56,490,494,495,182,187,217,970,961,969,971,56,490,495,491,182,217,214,970,961,971,963,56,491,495,496,214,217,219,972,963,971,973,56,491,496,492,214,219,147,972,963,973,965,56,432,436,497,183,80,189,974,845,853,975,56,432,497,493,183,189,185,974,845,975,967,56,493,497,498,185,189,191,976,967,975,977,56,493,498,494,185,191,187,976,967,977,969,56,494,498,499,187,191,221,978,969,977,979,56,494,499,495,187,221,217,978,969,979,971,56,495,499,500,217,221,151,980,971,979,981,56,495,500,496,217,151,219,980,971,981,973,56,436,440,501,64,152,155,982,853,861,983,56,436,501,497,64,155,156,982,853,983,975,56,497,501,502,156,155,159,984,975,983,985,56,497,502,498,156,159,160,984,975,985,977,56,498,502,503,160,159,194,986,977,985,987,56,498,503,499,160,194,195,986,977,987,979,56,499,503,504,195,194,198,988,979,987,989,56,499,504,500,195,198,135,988,979,989,981,56,440,444,505,152,68,162,990,861,869,991,56,440,505,501,152,162,155,990,861,991,983,56,501,505,506,155,162,164,992,983,991,993,56,501,506,502,155,164,159,992,983,993,985,56,502,506,507,159,164,200,994,985,993,995,56,502,507,503,159,200,194,994,985,995,987,56,503,507,508,194,200,139,996,987,995,997,56,503,508,504,194,139,198,996,987,997,989,56,444,448,509,68,165,167,998,869,877,999,56,444,509,505,68,167,162,998,869,999,991,56,505,509,510,162,167,169,1000,991,999,1001,56,505,510,506,162,169,164,1000,991,1001,993,56,506,510,511,164,169,203,1002,993,1001,1003,56,506,511,507,164,203,200,1002,993,1003,995,56,507,511,512,200,203,205,1004,995,1003,1005,56,507,512,508,200,205,139,1004,995,1005,997,56,448,452,513,165,72,171,1006,877,885,1007,56,448,513,509,165,171,167,1006,877,1007,999,56,509,513,514,167,171,173,1008,999,1007,1009,56,509,514,510,167,173,169,1008,999,1009,1001,56,510,514,515,169,173,207,1010,1001,1009,1011,56,510,515,511,169,207,203,1010,1001,1011,1003,56,511,515,516,203,207,143,1012,1003,1011,1013,56,511,516,512,203,143,205,1012,1003,1013,1005,56,452,456,517,72,174,176,1014,885,893,1015,56,452,517,513,72,176,171,1014,885,1015,1007,56,513,517,518,171,176,178,1016,1007,1015,1017,56,513,518,514,171,178,173,1016,1007,1017,1009,56,514,518,519,173,178,210,1018,1009,1017,1019,56,514,519,515,173,210,207,1018,1009,1019,1011,56,515,519,520,207,210,212,1020,1011,1019,1021,56,515,520,516,207,212,143,1020,1011,1021,1013,56,456,460,521,174,76,180,1022,893,901,1023,56,456,521,517,174,180,176,1022,893,1023,1015,56,517,521,522,176,180,182,1024,1015,1023,1025,56,517,522,518,176,182,178,1024,1015,1025,1017,56,518,522,523,178,182,214,1026,1017,1025,1027,56,518,523,519,178,214,210,1026,1017,1027,1019,56,519,523,524,210,214,147,1028,1019,1027,1029,56,519,524,520,210,147,212,1028,1019,1029,1021,56,460,464,525,76,183,185,1030,901,909,1031,56,460,525,521,76,185,180,1030,901,1031,1023,56,521,525,526,180,185,187,1032,1023,1031,1033,56,521,526,522,180,187,182,1032,1023,1033,1025,56,522,526,527,182,187,217,1034,1025,1033,1035,56,522,527,523,182,217,214,1034,1025,1035,1027,56,523,527,528,214,217,219,1036,1027,1035,1037,56,523,528,524,214,219,147,1036,1027,1037,1029,56,464,408,466,183,80,189,1038,909,797,916,56,464,466,525,183,189,185,1038,909,916,1031,56,525,466,468,185,189,191,1039,1031,916,919,56,525,468,526,185,191,187,1039,1031,919,1033,56,526,468,470,187,191,221,1040,1033,919,922,56,526,470,527,187,221,217,1040,1033,922,1035,56,527,470,472,217,221,151,1041,1035,922,925,56,527,472,528,217,151,219,1041,1035,925,1037]}}],\"materials\":[{\"uuid\":\"7AAB18E5-FF88-4A82-8018-4DF34EDB7539\",\"type\":\"MeshPhongMaterial\",\"color\":16714940,\"ambient\":16714940,\"emissive\":0,\"specular\":0,\"shininess\":50,\"opacity\":1,\"transparent\":false,\"wireframe\":false}],\"object\":{\"uuid\":\"0D4F494E-35AD-4D5B-9696-7DF60B73E7F0\",\"name\":\"Teapot001\",\"type\":\"Mesh\",\"geometry\":\"15930b1c-1b50-4926-a0ac-df433b9c4f96\",\"material\":\"7AAB18E5-FF88-4A82-8018-4DF34EDB7539\",\"castShadow\":true,\"receiveShadow\":true,\"matrix\":[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}}"
  },
  {
    "path": "example/customrender.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - customrender</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../lib/require.js\"></script>\n    <script src=\"../lib/config.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, spring;\n    var mesh;\n\n    function init() {\n        loadModel(initAll);\n    }\n\n    function initAll() {\n        initScene();\n        initLights();\n        initProton();\n        addStats();\n        animate();\n    }\n\n    function initScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function initLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function initProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n\n        //add custom renderer\n        var renderer = new Proton.CustomRender();\n        renderer.onParticleCreated = function(p) {\n            //p.target = mesh.clone();\n            p.target = this.targetPool.get(mesh);\n            p.target.position.copy(p.p);\n            scene.add(p.target);\n        }\n\n        renderer.onParticleUpdate = function(p) {\n            p.target.position.copy(p.p);\n            p.target.rotation.set(p.rotation.x, p.rotation.y, p.rotation.z);\n\n            var scale = p.scale * 30;\n            p.target.scale.set(scale, scale, scale);\n        }\n\n        renderer.onParticleDead = function(p) {\n            this.targetPool.expire(p.target);\n            scene.remove(p.target);\n            p.target = null;\n        }\n\n        proton.addRender(renderer);\n    }\n\n    //load model\n    function loadModel(callback) {\n        var material = new THREE.MeshNormalMaterial();\n        var loader = new THREE.JSONLoader();\n\n        loader.load('./assets/suzanne.js', function(geometry) {\n            geometry.computeVertexNormals();\n            mesh = new THREE.Mesh(geometry, material);\n            callback();\n        });\n    }\n\n    function createEmitter() {\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(4, 8), new Proton.Span(.2, .5));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(100));\n        emitter.addInitialize(new Proton.Life(2, 4));\n        emitter.addInitialize(new Proton.Velocity(400, new Proton.Vector3D(0, 1, 0), 60));\n\n        // //emitter.addBehaviour(new Proton.RandomDrift(30, 30, 30, .05));\n        emitter.addBehaviour(new Proton.Rotate(\"random\", \"random\"));\n        emitter.addBehaviour(new Proton.Scale(1, .1));\n        emitter.addBehaviour(new Proton.G(6));\n\n        var zone = new Proton.BoxZone(600);\n        zone.friction = 0.95;\n        zone.max = 7;\n        emitter.addBehaviour(new Proton.CrossZone(zone, \"bound\"));\n        emitter.addBehaviour(new Proton.Color(0xff0000, 'random', Infinity, Proton.easeOutQuart));\n\n        emitter.p.x = 0;\n        emitter.p.y = 0;\n        emitter.emit();\n        Proton.Debug.drawZone(proton, scene, zone);\n\n        return emitter;\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    var tha = 0;\n\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n\n        tha += .005;\n        camera.lookAt(scene.position);\n        camera.position.x = Math.sin(tha) * 500;\n        camera.position.z = Math.cos(tha) * 500;\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/eightdiagrams.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - eightdiagrams</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter1, emitter2, R;\n    var camera, scene, renderer, stats, clock, spring, controls;\n\n    init();\n    function init() {\n        addScene();\n        addControls();\n        addLights();\n        addStars();\n        addProton();\n        //addInteraction();\n        addStats();\n        animate();\n    }\n\n    function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n    }\n\n    function addLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function addStars() {\n        var geometry = new THREE.Geometry();\n        for (var i = 0; i < 10000; i++) {\n            var vertex = new THREE.Vector3();\n            vertex.x = THREE.Math.randFloatSpread(2000);\n            vertex.y = THREE.Math.randFloatSpread(2000);\n            vertex.z = THREE.Math.randFloatSpread(2000);\n            geometry.vertices.push(vertex);\n        }\n        var particles = new THREE.Points(geometry, new THREE.PointsMaterial({\n            color: 0x888888\n        }));\n        scene.add(particles);\n    }\n\n    function addProton() {\n        proton = new Proton();\n\n        R = 70;\n        emitter1 = createEmitter(R, 0, '#4F1500', '#0029FF');\n        emitter2 = createEmitter(-R, 0, '#004CFE', '#6600FF');\n\n        proton.addEmitter(emitter1);\n        proton.addEmitter(emitter2);\n        proton.addRender(new Proton.SpriteRender(scene));\n\n    }\n\n    function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            color: 0xff0000,\n            blending: THREE.AdditiveBlending,\n            fog: true\n        });\n        return new THREE.Sprite(material);\n    }\n\n    function createEmitter(x, y, color1, color2) {\n        var emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(5, 7), new Proton.Span(.01, .02));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Life(2));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n        emitter.addInitialize(new Proton.Radius(80));\n        emitter.addInitialize(new Proton.V(200, new Proton.Vector3D(0, 0, -1), 0));\n\n\n        emitter.addBehaviour(new Proton.Alpha(1, 0));\n        emitter.addBehaviour(new Proton.Color(color1, color2));\n        emitter.addBehaviour(new Proton.Scale(1, 0.5));\n        emitter.addBehaviour(new Proton.CrossZone(new Proton.ScreenZone(camera, renderer), 'dead'));\n\n\n        emitter.addBehaviour(new Proton.Force(0, 0, -20));\n        // emitter.addBehaviour(new Proton.Attraction({\n        //     x: 0,\n        //     y: 0,\n        //     z: 0\n        // }, 5, 250));\n\n\n\n        emitter.p.x = x;\n        emitter.p.y = y;\n        emitter.emit();\n\n        return emitter;\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        animateEmitter();\n        render();\n        stats.end();\n    }\n\n    var ctha = 0;\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        //controls.update();\n\n        camera.lookAt(scene.position);\n        ctha += .02;\n        camera.position.x = Math.sin(ctha) * 500;\n        camera.position.z = Math.cos(ctha) * 500;\n        camera.position.y = Math.sin(ctha) * 500;\n\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    var tha = 0;\n\n    function animateEmitter() {\n        tha += .13;\n        emitter1.p.x = R * Math.cos(tha);\n        emitter1.p.y = R * Math.sin(tha);\n\n        emitter2.p.x = R * Math.cos(tha + Math.PI / 2);\n        emitter2.p.y = R * Math.sin(tha + Math.PI / 2);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/followemitter.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>three.proton - eightdiagrams</title>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\" />\n    <style type=\"text/css\">\n      body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n      }\n    </style>\n  </head>\n\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../lib/require.js\"></script>\n    <script src=\"../lib/config.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n      var proton, emitter, R, particles;\n      var camera, scene, renderer, clock;\n\n      function init() {\n        addScene();\n        addLights();\n        addStars();\n        addProton();\n        animate();\n      }\n\n      function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener(\"resize\", onWindowResize, false);\n      }\n\n      function addLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n      }\n\n      function addStars() {\n        var geometry = new THREE.Geometry();\n        for (var i = 0; i < 10000; i++) {\n          var vertex = new THREE.Vector3();\n          vertex.x = THREE.Math.randFloatSpread(2000);\n          vertex.y = THREE.Math.randFloatSpread(2000);\n          vertex.z = THREE.Math.randFloatSpread(2000);\n          geometry.vertices.push(vertex);\n        }\n\n        particles = new THREE.Points(\n          geometry,\n          new THREE.PointsMaterial({\n            color: 0x888888\n          })\n        );\n\n        scene.add(particles);\n      }\n\n      function addProton() {\n        proton = new Proton();\n        emitter = new Proton.FollowEmitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(5, 7), new Proton.Span(0.01, 0.02));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Life(2));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n        emitter.addInitialize(new Proton.Radius(40));\n        emitter.addInitialize(new Proton.V(200, new Proton.Vector3D(0, 0, -1), 0));\n\n        emitter.addBehaviour(new Proton.Alpha(1, 0));\n        emitter.addBehaviour(new Proton.Color(\"#4F1500\", \"#0029FF\"));\n        emitter.addBehaviour(new Proton.Scale(1, 0.5));\n        emitter.addBehaviour(new Proton.CrossZone(new Proton.ScreenZone(camera, renderer), \"dead\"));\n\n        emitter.addBehaviour(new Proton.Force(0, 0, -20));\n        emitter.setCameraAndRenderer(camera, renderer);\n\n        emitter.emit();\n\n        proton.addEmitter(emitter);\n        proton.addRender(new Proton.SpriteRender(scene));\n      }\n\n      function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n          map: map,\n          color: 0xff0000,\n          blending: THREE.AdditiveBlending,\n          fog: true\n        });\n        return new THREE.Sprite(material);\n      }\n\n      function animate() {\n        requestAnimationFrame(animate);\n        render();\n      }\n\n      function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        camera.lookAt(scene.position);\n        particles.rotation.y += 0.01;\n\n        Proton.Debug.renderInfo(proton, 3);\n      }\n\n      function onWindowResize() {}\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "example/helloworld.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #000;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n\n    .tips {\n        position: absolute;\n        top: 10px;\n        right: 20px;\n        color: #fff;\n        font-size: 14px;\n        text-align: right;\n        padding: 6px 15px;\n        background: rgba(0,0,0,.7);\n    }\n    </style>\n</head>\n\n<body>\n    <div class=\"tips\">Please press the \"w\" key\n        <br><span id=\"info\">Add Behaviours</span>\n    </div>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../lib/require.js\"></script>\n    <script src=\"../lib/config.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter1, emitter2;\n    var camera, scene, renderer, stats, clock, controls;\n\n    function init() {\n        initScene();\n        initLights();\n        initProton();\n        initPlane();\n        initControls();\n        addStats();\n        animate();\n        keydownEvent();\n    }\n\n    function initScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        renderer.setClearColor(0xaaccff);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function keydownEvent() {\n        var num = 0;\n\n        document.onkeydown = function(e) {\n            var keynum = window.event ? e.keyCode : e.which;\n            if (keynum == 87) {\n                num++;\n\n                switch (num) {\n                    case 1:\n                        var color = new Proton.Color('random', 'random', Infinity, Proton.easeOutQuart);\n                        addBehaviour(color);\n                        addInfo(\": Color\");\n                        break;\n\n                    case 2:\n                        var zone = new Proton.BoxZone(400);\n                        addBehaviour(new Proton.CrossZone(zone, \"bound\"));\n                        addInfo(\"+CrossZone\");\n                        break;\n\n                    case 3:\n                        var force = new Proton.Force(1, 0, -.1);\n                        addBehaviour(force);\n                        addInfo(\"+Force\");\n                        break;\n\n                    case 4:\n                        var spring = new Proton.Spring(0, 0, 0);\n                        addBehaviour(spring);\n                        addInfo(\"+Spring\");\n                        break;\n\n                    case 5:\n                        var repulsion = new Proton.Repulsion(new Proton.Vector3D(0, -100, 0), 2, 200);\n                        addBehaviour(repulsion);\n                        addInfo(\"+Repulsion\");\n                        break;\n\n                    default:\n\n                }\n            }\n        }\n\n        function addInfo(info) {\n            document.getElementById(\"info\").innerText += info;\n        }\n\n        function addBehaviour(behaviour) {\n            emitter1.addBehaviour(behaviour);\n            emitter2.addBehaviour(behaviour);\n        }\n    }\n\n    function initLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n\n        var spotLight = new THREE.SpotLight(0xffffff, .5);\n        spotLight.position.set(0, 500, 100);\n        scene.add(spotLight);\n        spotLight.lookAt(scene);\n    }\n\n    function initControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n        //controls.addEventListener('change', render);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function initPlane() {\n        var groundGeo = new THREE.PlaneBufferGeometry(10000, 10000);\n        var groundMat = new THREE.MeshPhongMaterial({\n            color: 0xffffff,\n            specular: 0x050505\n        });\n        groundMat.color.setHSL(0.095, 1, 0.75);\n\n        var ground = new THREE.Mesh(groundGeo, groundMat);\n        ground.rotation.x = -Math.PI / 2;\n        ground.position.y = -200;\n        scene.add(ground);\n        //ground.receiveShadow = true;\n    }\n\n    function initProton() {\n        proton = new Proton();\n\n        emitter1 = createEmitter({\n            p: {\n                x: -100,\n                y: 0\n            },\n            Body: createMesh(\"sphere\")\n        })\n\n        emitter2 = createEmitter({\n            p: {\n                x: 100,\n                y: 0\n            },\n            Body: createMesh(\"cube\")\n        })\n\n        proton.addEmitter(emitter1);\n        proton.addEmitter(emitter2);\n\n        proton.addRender(new Proton.MeshRender(scene));\n\n        //Proton.Debug.drawZone(proton,scene,zone2);\n        Proton.Debug.drawEmitter(proton, scene, emitter1);\n        Proton.Debug.drawEmitter(proton, scene, emitter2);\n    }\n\n    function createMesh(geo) {\n        if (geo == \"sphere\") {\n            var geometry = new THREE.SphereGeometry(10, 8, 8);\n            var material = new THREE.MeshLambertMaterial({\n                color: \"#ff0000\"\n            });\n        } else {\n            var geometry = new THREE.BoxGeometry(20, 20, 20);\n            var material = new THREE.MeshLambertMaterial({\n                color: \"#00ffcc\"\n            });\n        }\n\n        var mesh = new THREE.Mesh(geometry, material);\n        return mesh;\n    }\n\n\n    function createEmitter(obj) {\n        var emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(5, 10), new Proton.Span(.1, .25));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(10));\n        emitter.addInitialize(new Proton.Life(2, 4));\n        emitter.addInitialize(new Proton.Body(obj.Body));\n        emitter.addInitialize(new Proton.Position(new Proton.BoxZone(100)));\n        emitter.addInitialize(new Proton.Velocity(200, new Proton.Vector3D(0, 1, 1), 30));\n\n        emitter.addBehaviour(new Proton.Rotate(\"random\", \"random\"));\n        emitter.addBehaviour(new Proton.Scale(1, 0.1));\n        //Gravity\n        emitter.addBehaviour(new Proton.Gravity(3));\n\n        emitter.p.x = obj.p.x;\n        emitter.p.y = obj.p.y;\n        emitter.emit();\n        return emitter;\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        controls.update();\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/js/extras/GravityWell.js",
    "content": "(function(Proton, undefined) {\n\tfunction GravityWell(centerPoint, force, life, easing) {\n\t\tGravityWell._super_.call(this, life, easing);\n\t\tthis.distanceVec = new Proton.Vector2D();\n\t\tthis.centerPoint = Proton.Util.initValue(centerPoint, new Proton.Vector2D);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tthis.name = \"GravityWell\";\n\t}\n\n\n\tProton.Util.inherits(GravityWell, Proton.Behaviour);\n\tGravityWell.prototype.reset = function(centerPoint, force, life, easing) {\n\t\tthis.distanceVec = new Proton.Vector2D();\n\t\tthis.centerPoint = Proton.Util.initValue(centerPoint, new Proton.Vector2D);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tif (life)\n\t\t\tGravityWell._super_.prototype.reset.call(this, life, easing);\n\t};\n\tGravityWell.prototype.initialize = function(particle) {\n\n\t};\n\n\tGravityWell.prototype.applyBehaviour = function(particle, time, index) {\n\t\tthis.distanceVec.set(this.centerPoint.x - particle.p.x, this.centerPoint.y - particle.p.y);\n\t\tvar distanceSq = this.distanceVec.lengthSq();\n\t\tif (distanceSq != 0) {\n\t\t\tvar distance = this.distanceVec.length();\n\t\t\tvar factor = (this.force * time ) / (distanceSq * distance );\n\t\t\tparticle.v.x += factor * this.distanceVec.x;\n\t\t\tparticle.v.y += factor * this.distanceVec.y;\n\t\t}\n\t}\n\n\tProton.GravityWell = GravityWell;\n})(Proton);\n"
  },
  {
    "path": "example/js/extras/PosSpring.js",
    "content": "(function(Proton, undefined) {\n    function PosSpring(spring, friction, life, easing) {\n        PosSpring._super_.call(this, life, easing);\n        PosSpring.prototype.reset(spring, friction);\n        this.name = \"Spring\";\n    }\n\n    Proton.Util.inherits(PosSpring, Proton.Behaviour);\n    PosSpring.prototype.reset = function(spring, friction) {\n        this.spring = spring || .1;\n        this.friction = friction || .98;\n    }\n\n    PosSpring.prototype.initialize = function(particle) {\n        particle.transform.pos = particle.p.clone();\n    };\n\n    PosSpring.prototype.applyBehaviour = function(particle, time, index) {\n        PosSpring._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        particle.v.x += (particle.transform.pos.x - particle.p.x) * this.spring;\n        particle.v.y += (particle.transform.pos.y - particle.p.y) * this.spring;\n        particle.v.z += (particle.transform.pos.z - particle.p.z) * this.spring;\n    };\n    \n    Proton.PosSpring = PosSpring;\n})(Proton);\n"
  },
  {
    "path": "example/js/extras/proton.tool.js",
    "content": "(function(THREE) {\n    Proton.toScreenXY = function() {\n        var vec = {};\n\n        return function(position, camera, jqdiv) {\n            var pos = position.clone();\n            projScreenMat = new THREE.Matrix4();\n            projScreenMat.multiply(camera.projectionMatrix, camera.matrixWorldInverse);\n            projScreenMat.multiplyVector3(pos);\n\n            vec.x = (pos.x + 1) * jqdiv.width() / 2 + jqdiv.offset().left;\n            vec.y = (-pos.y + 1) * jqdiv.height() / 2 + jqdiv.offset().top;\n\n            return vec;\n        }\n    }();\n})(THREE);\n"
  },
  {
    "path": "example/js/lib/FlyControls.js",
    "content": "/**\n * @author James Baicoianu / http://www.baicoianu.com/\n */\n\nTHREE.FlyControls = function ( object, domElement ) {\n\n\tthis.object = object;\n\n\tthis.domElement = ( domElement !== undefined ) ? domElement : document;\n\tif ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 );\n\n\t// API\n\n\tthis.movementSpeed = 1.0;\n\tthis.rollSpeed = 0.005;\n\n\tthis.dragToLook = false;\n\tthis.autoForward = false;\n\n\t// disable default target object behavior\n\n\t// internals\n\n\tthis.tmpQuaternion = new THREE.Quaternion();\n\n\tthis.mouseStatus = 0;\n\n\tthis.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 };\n\tthis.moveVector = new THREE.Vector3( 0, 0, 0 );\n\tthis.rotationVector = new THREE.Vector3( 0, 0, 0 );\n\n\tthis.handleEvent = function ( event ) {\n\n\t\tif ( typeof this[ event.type ] == 'function' ) {\n\n\t\t\tthis[ event.type ]( event );\n\n\t\t}\n\n\t};\n\n\tthis.keydown = function( event ) {\n\n\t\tif ( event.altKey ) {\n\n\t\t\treturn;\n\n\t\t}\n\n\t\t//event.preventDefault();\n\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase 16: /* shift */ this.movementSpeedMultiplier = .1; break;\n\n\t\t\tcase 87: /*W*/ this.moveState.forward = 1; break;\n\t\t\tcase 83: /*S*/ this.moveState.back = 1; break;\n\n\t\t\tcase 65: /*A*/ this.moveState.left = 1; break;\n\t\t\tcase 68: /*D*/ this.moveState.right = 1; break;\n\n\t\t\tcase 82: /*R*/ this.moveState.up = 1; break;\n\t\t\tcase 70: /*F*/ this.moveState.down = 1; break;\n\n\t\t\tcase 38: /*up*/ this.moveState.pitchUp = 1; break;\n\t\t\tcase 40: /*down*/ this.moveState.pitchDown = 1; break;\n\n\t\t\tcase 37: /*left*/ this.moveState.yawLeft = 1; break;\n\t\t\tcase 39: /*right*/ this.moveState.yawRight = 1; break;\n\n\t\t\tcase 81: /*Q*/ this.moveState.rollLeft = 1; break;\n\t\t\tcase 69: /*E*/ this.moveState.rollRight = 1; break;\n\n\t\t}\n\n\t\tthis.updateMovementVector();\n\t\tthis.updateRotationVector();\n\n\t};\n\n\tthis.keyup = function( event ) {\n\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase 16: /* shift */ this.movementSpeedMultiplier = 1; break;\n\n\t\t\tcase 87: /*W*/ this.moveState.forward = 0; break;\n\t\t\tcase 83: /*S*/ this.moveState.back = 0; break;\n\n\t\t\tcase 65: /*A*/ this.moveState.left = 0; break;\n\t\t\tcase 68: /*D*/ this.moveState.right = 0; break;\n\n\t\t\tcase 82: /*R*/ this.moveState.up = 0; break;\n\t\t\tcase 70: /*F*/ this.moveState.down = 0; break;\n\n\t\t\tcase 38: /*up*/ this.moveState.pitchUp = 0; break;\n\t\t\tcase 40: /*down*/ this.moveState.pitchDown = 0; break;\n\n\t\t\tcase 37: /*left*/ this.moveState.yawLeft = 0; break;\n\t\t\tcase 39: /*right*/ this.moveState.yawRight = 0; break;\n\n\t\t\tcase 81: /*Q*/ this.moveState.rollLeft = 0; break;\n\t\t\tcase 69: /*E*/ this.moveState.rollRight = 0; break;\n\n\t\t}\n\n\t\tthis.updateMovementVector();\n\t\tthis.updateRotationVector();\n\n\t};\n\n\tthis.mousedown = function( event ) {\n\n\t\tif ( this.domElement !== document ) {\n\n\t\t\tthis.domElement.focus();\n\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tif ( this.dragToLook ) {\n\n\t\t\tthis.mouseStatus ++;\n\n\t\t} else {\n\n\t\t\tswitch ( event.button ) {\n\n\t\t\t\tcase 0: this.moveState.forward = 1; break;\n\t\t\t\tcase 2: this.moveState.back = 1; break;\n\n\t\t\t}\n\n\t\t\tthis.updateMovementVector();\n\n\t\t}\n\n\t};\n\n\tthis.mousemove = function( event ) {\n\n\t\tif ( ! this.dragToLook || this.mouseStatus > 0 ) {\n\n\t\t\tvar container = this.getContainerDimensions();\n\t\t\tvar halfWidth  = container.size[ 0 ] / 2;\n\t\t\tvar halfHeight = container.size[ 1 ] / 2;\n\n\t\t\tthis.moveState.yawLeft   = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth  ) / halfWidth;\n\t\t\tthis.moveState.pitchDown =   ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight;\n\n\t\t\tthis.updateRotationVector();\n\n\t\t}\n\n\t};\n\n\tthis.mouseup = function( event ) {\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tif ( this.dragToLook ) {\n\n\t\t\tthis.mouseStatus --;\n\n\t\t\tthis.moveState.yawLeft = this.moveState.pitchDown = 0;\n\n\t\t} else {\n\n\t\t\tswitch ( event.button ) {\n\n\t\t\t\tcase 0: this.moveState.forward = 0; break;\n\t\t\t\tcase 2: this.moveState.back = 0; break;\n\n\t\t\t}\n\n\t\t\tthis.updateMovementVector();\n\n\t\t}\n\n\t\tthis.updateRotationVector();\n\n\t};\n\n\tthis.update = function( delta ) {\n\n\t\tvar moveMult = delta * this.movementSpeed;\n\t\tvar rotMult = delta * this.rollSpeed;\n\n\t\tthis.object.translateX( this.moveVector.x * moveMult );\n\t\tthis.object.translateY( this.moveVector.y * moveMult );\n\t\tthis.object.translateZ( this.moveVector.z * moveMult );\n\n\t\tthis.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();\n\t\tthis.object.quaternion.multiply( this.tmpQuaternion );\n\n\t\t// expose the rotation vector for convenience\n\t\tthis.object.rotation.setFromQuaternion( this.object.quaternion, this.object.rotation.order );\n\n\n\t};\n\n\tthis.updateMovementVector = function() {\n\n\t\tvar forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0;\n\n\t\tthis.moveVector.x = ( - this.moveState.left    + this.moveState.right );\n\t\tthis.moveVector.y = ( - this.moveState.down    + this.moveState.up );\n\t\tthis.moveVector.z = ( - forward + this.moveState.back );\n\n\t\t//console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );\n\n\t};\n\n\tthis.updateRotationVector = function() {\n\n\t\tthis.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp );\n\t\tthis.rotationVector.y = ( - this.moveState.yawRight  + this.moveState.yawLeft );\n\t\tthis.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft );\n\n\t\t//console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );\n\n\t};\n\n\tthis.getContainerDimensions = function() {\n\n\t\tif ( this.domElement != document ) {\n\n\t\t\treturn {\n\t\t\t\tsize\t: [ this.domElement.offsetWidth, this.domElement.offsetHeight ],\n\t\t\t\toffset\t: [ this.domElement.offsetLeft,  this.domElement.offsetTop ]\n\t\t\t};\n\n\t\t} else {\n\n\t\t\treturn {\n\t\t\t\tsize\t: [ window.innerWidth, window.innerHeight ],\n\t\t\t\toffset\t: [ 0, 0 ]\n\t\t\t};\n\n\t\t}\n\n\t};\n\n\tfunction bind( scope, fn ) {\n\n\t\treturn function () {\n\n\t\t\tfn.apply( scope, arguments );\n\n\t\t};\n\n\t}\n\n\tfunction contextmenu( event ) {\n\n\t\tevent.preventDefault();\n\n\t}\n\n\tthis.dispose = function() {\n\n\t\tthis.domElement.removeEventListener( 'contextmenu', contextmenu, false );\n\t\tthis.domElement.removeEventListener( 'mousedown', _mousedown, false );\n\t\tthis.domElement.removeEventListener( 'mousemove', _mousemove, false );\n\t\tthis.domElement.removeEventListener( 'mouseup', _mouseup, false );\n\n\t\twindow.removeEventListener( 'keydown', _keydown, false );\n\t\twindow.removeEventListener( 'keyup', _keyup, false );\n\n\t}\n\n\tvar _mousemove = bind( this, this.mousemove );\n\tvar _mousedown = bind( this, this.mousedown );\n\tvar _mouseup = bind( this, this.mouseup );\n\tvar _keydown = bind( this, this.keydown );\n\tvar _keyup = bind( this, this.keyup );\n\n\tthis.domElement.addEventListener( 'contextmenu', contextmenu, false );\n\n\tthis.domElement.addEventListener( 'mousemove', _mousemove, false );\n\tthis.domElement.addEventListener( 'mousedown', _mousedown, false );\n\tthis.domElement.addEventListener( 'mouseup',   _mouseup, false );\n\n\twindow.addEventListener( 'keydown', _keydown, false );\n\twindow.addEventListener( 'keyup',   _keyup, false );\n\n\tthis.updateMovementVector();\n\tthis.updateRotationVector();\n\n};\n"
  },
  {
    "path": "example/js/lib/TrackballControls.js",
    "content": "/**\n * @author Eberhard Graether / http://egraether.com/\n * @author Mark Lundin \t/ http://mark-lundin.com\n * @author Simone Manini / http://daron1337.github.io\n * @author Luca Antiga \t/ http://lantiga.github.io\n */\n\nTHREE.TrackballControls = function ( object, domElement ) {\n\n\tvar _this = this;\n\tvar STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };\n\n\tthis.object = object;\n\tthis.domElement = ( domElement !== undefined ) ? domElement : document;\n\n\t// API\n\n\tthis.enabled = true;\n\n\tthis.screen = { left: 0, top: 0, width: 0, height: 0 };\n\n\tthis.rotateSpeed = 1.0;\n\tthis.zoomSpeed = 1.2;\n\tthis.panSpeed = 0.3;\n\n\tthis.noRotate = false;\n\tthis.noZoom = false;\n\tthis.noPan = false;\n\n\tthis.staticMoving = false;\n\tthis.dynamicDampingFactor = 0.2;\n\n\tthis.minDistance = 0;\n\tthis.maxDistance = Infinity;\n\n\tthis.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];\n\n\t// internals\n\n\tthis.target = new THREE.Vector3();\n\n\tvar EPS = 0.000001;\n\n\tvar lastPosition = new THREE.Vector3();\n\n\tvar _state = STATE.NONE,\n\t_prevState = STATE.NONE,\n\n\t_eye = new THREE.Vector3(),\n\n\t_movePrev = new THREE.Vector2(),\n\t_moveCurr = new THREE.Vector2(),\n\n\t_lastAxis = new THREE.Vector3(),\n\t_lastAngle = 0,\n\n\t_zoomStart = new THREE.Vector2(),\n\t_zoomEnd = new THREE.Vector2(),\n\n\t_touchZoomDistanceStart = 0,\n\t_touchZoomDistanceEnd = 0,\n\n\t_panStart = new THREE.Vector2(),\n\t_panEnd = new THREE.Vector2();\n\n\t// for reset\n\n\tthis.target0 = this.target.clone();\n\tthis.position0 = this.object.position.clone();\n\tthis.up0 = this.object.up.clone();\n\n\t// events\n\n\tvar changeEvent = { type: 'change' };\n\tvar startEvent = { type: 'start' };\n\tvar endEvent = { type: 'end' };\n\n\n\t// methods\n\n\tthis.handleResize = function () {\n\n\t\tif ( this.domElement === document ) {\n\n\t\t\tthis.screen.left = 0;\n\t\t\tthis.screen.top = 0;\n\t\t\tthis.screen.width = window.innerWidth;\n\t\t\tthis.screen.height = window.innerHeight;\n\n\t\t} else {\n\n\t\t\tvar box = this.domElement.getBoundingClientRect();\n\t\t\t// adjustments come from similar code in the jquery offset() function\n\t\t\tvar d = this.domElement.ownerDocument.documentElement;\n\t\t\tthis.screen.left = box.left + window.pageXOffset - d.clientLeft;\n\t\t\tthis.screen.top = box.top + window.pageYOffset - d.clientTop;\n\t\t\tthis.screen.width = box.width;\n\t\t\tthis.screen.height = box.height;\n\n\t\t}\n\n\t};\n\n\tthis.handleEvent = function ( event ) {\n\n\t\tif ( typeof this[ event.type ] == 'function' ) {\n\n\t\t\tthis[ event.type ]( event );\n\n\t\t}\n\n\t};\n\n\tvar getMouseOnScreen = ( function () {\n\n\t\tvar vector = new THREE.Vector2();\n\n\t\treturn function getMouseOnScreen( pageX, pageY ) {\n\n\t\t\tvector.set(\n\t\t\t\t( pageX - _this.screen.left ) / _this.screen.width,\n\t\t\t\t( pageY - _this.screen.top ) / _this.screen.height\n\t\t\t);\n\n\t\t\treturn vector;\n\n\t\t};\n\n\t}() );\n\n\tvar getMouseOnCircle = ( function () {\n\n\t\tvar vector = new THREE.Vector2();\n\n\t\treturn function getMouseOnCircle( pageX, pageY ) {\n\n\t\t\tvector.set(\n\t\t\t\t( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),\n\t\t\t\t( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional\n\t\t\t);\n\n\t\t\treturn vector;\n\n\t\t};\n\n\t}() );\n\n\tthis.rotateCamera = ( function() {\n\n\t\tvar axis = new THREE.Vector3(),\n\t\t\tquaternion = new THREE.Quaternion(),\n\t\t\teyeDirection = new THREE.Vector3(),\n\t\t\tobjectUpDirection = new THREE.Vector3(),\n\t\t\tobjectSidewaysDirection = new THREE.Vector3(),\n\t\t\tmoveDirection = new THREE.Vector3(),\n\t\t\tangle;\n\n\t\treturn function rotateCamera() {\n\n\t\t\tmoveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );\n\t\t\tangle = moveDirection.length();\n\n\t\t\tif ( angle ) {\n\n\t\t\t\t_eye.copy( _this.object.position ).sub( _this.target );\n\n\t\t\t\teyeDirection.copy( _eye ).normalize();\n\t\t\t\tobjectUpDirection.copy( _this.object.up ).normalize();\n\t\t\t\tobjectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();\n\n\t\t\t\tobjectUpDirection.setLength( _moveCurr.y - _movePrev.y );\n\t\t\t\tobjectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );\n\n\t\t\t\tmoveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );\n\n\t\t\t\taxis.crossVectors( moveDirection, _eye ).normalize();\n\n\t\t\t\tangle *= _this.rotateSpeed;\n\t\t\t\tquaternion.setFromAxisAngle( axis, angle );\n\n\t\t\t\t_eye.applyQuaternion( quaternion );\n\t\t\t\t_this.object.up.applyQuaternion( quaternion );\n\n\t\t\t\t_lastAxis.copy( axis );\n\t\t\t\t_lastAngle = angle;\n\n\t\t\t} else if ( ! _this.staticMoving && _lastAngle ) {\n\n\t\t\t\t_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );\n\t\t\t\t_eye.copy( _this.object.position ).sub( _this.target );\n\t\t\t\tquaternion.setFromAxisAngle( _lastAxis, _lastAngle );\n\t\t\t\t_eye.applyQuaternion( quaternion );\n\t\t\t\t_this.object.up.applyQuaternion( quaternion );\n\n\t\t\t}\n\n\t\t\t_movePrev.copy( _moveCurr );\n\n\t\t};\n\n\t}() );\n\n\n\tthis.zoomCamera = function () {\n\n\t\tvar factor;\n\n\t\tif ( _state === STATE.TOUCH_ZOOM_PAN ) {\n\n\t\t\tfactor = _touchZoomDistanceStart / _touchZoomDistanceEnd;\n\t\t\t_touchZoomDistanceStart = _touchZoomDistanceEnd;\n\t\t\t_eye.multiplyScalar( factor );\n\n\t\t} else {\n\n\t\t\tfactor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;\n\n\t\t\tif ( factor !== 1.0 && factor > 0.0 ) {\n\n\t\t\t\t_eye.multiplyScalar( factor );\n\n\t\t\t\tif ( _this.staticMoving ) {\n\n\t\t\t\t\t_zoomStart.copy( _zoomEnd );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tthis.panCamera = ( function() {\n\n\t\tvar mouseChange = new THREE.Vector2(),\n\t\t\tobjectUp = new THREE.Vector3(),\n\t\t\tpan = new THREE.Vector3();\n\n\t\treturn function panCamera() {\n\n\t\t\tmouseChange.copy( _panEnd ).sub( _panStart );\n\n\t\t\tif ( mouseChange.lengthSq() ) {\n\n\t\t\t\tmouseChange.multiplyScalar( _eye.length() * _this.panSpeed );\n\n\t\t\t\tpan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );\n\t\t\t\tpan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );\n\n\t\t\t\t_this.object.position.add( pan );\n\t\t\t\t_this.target.add( pan );\n\n\t\t\t\tif ( _this.staticMoving ) {\n\n\t\t\t\t\t_panStart.copy( _panEnd );\n\n\t\t\t\t} else {\n\n\t\t\t\t\t_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t};\n\n\t}() );\n\n\tthis.checkDistances = function () {\n\n\t\tif ( ! _this.noZoom || ! _this.noPan ) {\n\n\t\t\tif ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {\n\n\t\t\t\t_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );\n\t\t\t\t_zoomStart.copy( _zoomEnd );\n\n\t\t\t}\n\n\t\t\tif ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {\n\n\t\t\t\t_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );\n\t\t\t\t_zoomStart.copy( _zoomEnd );\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tthis.update = function () {\n\n\t\t_eye.subVectors( _this.object.position, _this.target );\n\n\t\tif ( ! _this.noRotate ) {\n\n\t\t\t_this.rotateCamera();\n\n\t\t}\n\n\t\tif ( ! _this.noZoom ) {\n\n\t\t\t_this.zoomCamera();\n\n\t\t}\n\n\t\tif ( ! _this.noPan ) {\n\n\t\t\t_this.panCamera();\n\n\t\t}\n\n\t\t_this.object.position.addVectors( _this.target, _eye );\n\n\t\t_this.checkDistances();\n\n\t\t_this.object.lookAt( _this.target );\n\n\t\tif ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {\n\n\t\t\t_this.dispatchEvent( changeEvent );\n\n\t\t\tlastPosition.copy( _this.object.position );\n\n\t\t}\n\n\t};\n\n\tthis.reset = function () {\n\n\t\t_state = STATE.NONE;\n\t\t_prevState = STATE.NONE;\n\n\t\t_this.target.copy( _this.target0 );\n\t\t_this.object.position.copy( _this.position0 );\n\t\t_this.object.up.copy( _this.up0 );\n\n\t\t_eye.subVectors( _this.object.position, _this.target );\n\n\t\t_this.object.lookAt( _this.target );\n\n\t\t_this.dispatchEvent( changeEvent );\n\n\t\tlastPosition.copy( _this.object.position );\n\n\t};\n\n\t// listeners\n\n\tfunction keydown( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\twindow.removeEventListener( 'keydown', keydown );\n\n\t\t_prevState = _state;\n\n\t\tif ( _state !== STATE.NONE ) {\n\n\t\t\treturn;\n\n\t\t} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {\n\n\t\t\t_state = STATE.ROTATE;\n\n\t\t} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {\n\n\t\t\t_state = STATE.ZOOM;\n\n\t\t} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {\n\n\t\t\t_state = STATE.PAN;\n\n\t\t}\n\n\t}\n\n\tfunction keyup( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\t_state = _prevState;\n\n\t\twindow.addEventListener( 'keydown', keydown, false );\n\n\t}\n\n\tfunction mousedown( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tif ( _state === STATE.NONE ) {\n\n\t\t\t_state = event.button;\n\n\t\t}\n\n\t\tif ( _state === STATE.ROTATE && ! _this.noRotate ) {\n\n\t\t\t_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );\n\t\t\t_movePrev.copy( _moveCurr );\n\n\t\t} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {\n\n\t\t\t_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n\t\t\t_zoomEnd.copy( _zoomStart );\n\n\t\t} else if ( _state === STATE.PAN && ! _this.noPan ) {\n\n\t\t\t_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n\t\t\t_panEnd.copy( _panStart );\n\n\t\t}\n\n\t\tdocument.addEventListener( 'mousemove', mousemove, false );\n\t\tdocument.addEventListener( 'mouseup', mouseup, false );\n\n\t\t_this.dispatchEvent( startEvent );\n\n\t}\n\n\tfunction mousemove( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tif ( _state === STATE.ROTATE && ! _this.noRotate ) {\n\n\t\t\t_movePrev.copy( _moveCurr );\n\t\t\t_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );\n\n\t\t} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {\n\n\t\t\t_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n\n\t\t} else if ( _state === STATE.PAN && ! _this.noPan ) {\n\n\t\t\t_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );\n\n\t\t}\n\n\t}\n\n\tfunction mouseup( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\t_state = STATE.NONE;\n\n\t\tdocument.removeEventListener( 'mousemove', mousemove );\n\t\tdocument.removeEventListener( 'mouseup', mouseup );\n\t\t_this.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction mousewheel( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tvar delta = 0;\n\n\t\tif ( event.wheelDelta ) {\n\n\t\t\t// WebKit / Opera / Explorer 9\n\n\t\t\tdelta = event.wheelDelta / 40;\n\n\t\t} else if ( event.detail ) {\n\n\t\t\t// Firefox\n\n\t\t\tdelta = - event.detail / 3;\n\n\t\t}\n\n\t\t_zoomStart.y += delta * 0.01;\n\t\t_this.dispatchEvent( startEvent );\n\t\t_this.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction touchstart( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\n\t\t\t\t_state = STATE.TOUCH_ROTATE;\n\t\t\t\t_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n\t\t\t\t_movePrev.copy( _moveCurr );\n\t\t\t\tbreak;\n\n\t\t\tdefault: // 2 or more\n\t\t\t\t_state = STATE.TOUCH_ZOOM_PAN;\n\t\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\t\t\t\t_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\t\tvar x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;\n\t\t\t\tvar y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;\n\t\t\t\t_panStart.copy( getMouseOnScreen( x, y ) );\n\t\t\t\t_panEnd.copy( _panStart );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t_this.dispatchEvent( startEvent );\n\n\t}\n\n\tfunction touchmove( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\n\t\t\t\t_movePrev.copy( _moveCurr );\n\t\t\t\t_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n\t\t\t\tbreak;\n\n\t\t\tdefault: // 2 or more\n\t\t\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\t\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\t\t\t\t_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );\n\n\t\t\t\tvar x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;\n\t\t\t\tvar y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;\n\t\t\t\t_panEnd.copy( getMouseOnScreen( x, y ) );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction touchend( event ) {\n\n\t\tif ( _this.enabled === false ) return;\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 0:\n\t\t\t\t_state = STATE.NONE;\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\t\t\t\t_state = STATE.TOUCH_ROTATE;\n\t\t\t\t_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );\n\t\t\t\t_movePrev.copy( _moveCurr );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\t_this.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction contextmenu( event ) {\n\n\t\tevent.preventDefault();\n\n\t}\n\n\tthis.dispose = function() {\n\n\t\tthis.domElement.removeEventListener( 'contextmenu', contextmenu, false );\n\t\tthis.domElement.removeEventListener( 'mousedown', mousedown, false );\n\t\tthis.domElement.removeEventListener( 'mousewheel', mousewheel, false );\n\t\tthis.domElement.removeEventListener( 'MozMousePixelScroll', mousewheel, false ); // firefox\n\n\t\tthis.domElement.removeEventListener( 'touchstart', touchstart, false );\n\t\tthis.domElement.removeEventListener( 'touchend', touchend, false );\n\t\tthis.domElement.removeEventListener( 'touchmove', touchmove, false );\n\n\t\tdocument.removeEventListener( 'mousemove', mousemove, false );\n\t\tdocument.removeEventListener( 'mouseup', mouseup, false );\n\n\t\twindow.removeEventListener( 'keydown', keydown, false );\n\t\twindow.removeEventListener( 'keyup', keyup, false );\n\n\t};\n\n\tthis.domElement.addEventListener( 'contextmenu', contextmenu, false );\n\tthis.domElement.addEventListener( 'mousedown', mousedown, false );\n\tthis.domElement.addEventListener( 'mousewheel', mousewheel, false );\n\tthis.domElement.addEventListener( 'MozMousePixelScroll', mousewheel, false ); // firefox\n\n\tthis.domElement.addEventListener( 'touchstart', touchstart, false );\n\tthis.domElement.addEventListener( 'touchend', touchend, false );\n\tthis.domElement.addEventListener( 'touchmove', touchmove, false );\n\n\twindow.addEventListener( 'keydown', keydown, false );\n\twindow.addEventListener( 'keyup', keyup, false );\n\n\tthis.handleResize();\n\n\t// force an update at start\n\tthis.update();\n\n};\n\nTHREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );\nTHREE.TrackballControls.prototype.constructor = THREE.TrackballControls;\n"
  },
  {
    "path": "example/js/lib/postprocessing/AdaptiveToneMappingPass.js",
    "content": "/**\n * @author miibond\n * Generate a texture that represents the luminosity of the current scene, adapted over time\n * to simulate the optic nerve responding to the amount of light it is receiving.\n * Based on a GDC2007 presentation by Wolfgang Engel titled \"Post-Processing Pipeline\"\n *\n * Full-screen tone-mapping shader based on http://www.graphics.cornell.edu/~jaf/publications/sig02_paper.pdf\n */\n\nTHREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.resolution = ( resolution !== undefined ) ? resolution : 256;\n\tthis.needsInit = true;\n\tthis.adaptive = adaptive !== undefined ? !! adaptive : true;\n\n\tthis.luminanceRT = null;\n\tthis.previousLuminanceRT = null;\n\tthis.currentLuminanceRT = null;\n\n\tif ( THREE.CopyShader === undefined )\n\t\tconsole.error( \"THREE.AdaptiveToneMappingPass relies on THREE.CopyShader\" );\n\n\tvar copyShader = THREE.CopyShader;\n\n\tthis.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );\n\n\tthis.materialCopy = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.copyUniforms,\n\t\tvertexShader: copyShader.vertexShader,\n\t\tfragmentShader: copyShader.fragmentShader,\n\t\tblending: THREE.NoBlending,\n\t\tdepthTest: false\n\n\t} );\n\n\tif ( THREE.LuminosityShader === undefined )\n\t\tconsole.error( \"THREE.AdaptiveToneMappingPass relies on THREE.LuminosityShader\" );\n\n\tthis.materialLuminance = new THREE.ShaderMaterial( {\n\n\t\tuniforms: THREE.UniformsUtils.clone( THREE.LuminosityShader.uniforms ),\n\t\tvertexShader: THREE.LuminosityShader.vertexShader,\n\t\tfragmentShader: THREE.LuminosityShader.fragmentShader,\n\t\tblending: THREE.NoBlending,\n\t} );\n\n\tthis.adaptLuminanceShader = {\n\t\tdefines: {\n\t\t\t\"MIP_LEVEL_1X1\" : ( Math.log( this.resolution ) / Math.log( 2.0 ) ).toFixed( 1 ),\n\t\t},\n\t\tuniforms: {\n\t\t\t\"lastLum\": { type: \"t\", value: null },\n\t\t\t\"currentLum\": { type: \"t\", value: null },\n\t\t\t\"delta\": { type: 'f', value: 0.016 },\n\t\t\t\"tau\": { type: 'f', value: 1.0 }\n\t\t},\n\t\tvertexShader: [\n\t\t\t\"varying vec2 vUv;\",\n\n\t\t\t\"void main() {\",\n\n\t\t\t\t\"vUv = uv;\",\n\t\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\t\"}\"\n\t\t].join( '\\n' ),\n\t\tfragmentShader: [\n\t\t\t\"varying vec2 vUv;\",\n\n\t\t\t\"uniform sampler2D lastLum;\",\n\t\t\t\"uniform sampler2D currentLum;\",\n\t\t\t\"uniform float delta;\",\n\t\t\t\"uniform float tau;\",\n\n\t\t\t\"void main() {\",\n\n\t\t\t\t\"vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );\",\n\t\t\t\t\"vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );\",\n\n\t\t\t\t\"float fLastLum = lastLum.r;\",\n\t\t\t\t\"float fCurrentLum = currentLum.r;\",\n\n\t\t\t\t//The adaption seems to work better in extreme lighting differences\n\t\t\t\t//if the input luminance is squared.\n\t\t\t\t\"fCurrentLum *= fCurrentLum;\",\n\n\t\t\t\t// Adapt the luminance using Pattanaik's technique\n\t\t\t\t\"float fAdaptedLum = fLastLum + (fCurrentLum - fLastLum) * (1.0 - exp(-delta * tau));\",\n\t\t\t\t// \"fAdaptedLum = sqrt(fAdaptedLum);\",\n\t\t\t\t\"gl_FragColor = vec4( vec3( fAdaptedLum ), 1.0 );\",\n\t\t\t\"}\",\n\t\t].join( '\\n' )\n\t};\n\n\tthis.materialAdaptiveLum = new THREE.ShaderMaterial( {\n\n\t\tuniforms: THREE.UniformsUtils.clone( this.adaptLuminanceShader.uniforms ),\n\t\tvertexShader: this.adaptLuminanceShader.vertexShader,\n\t\tfragmentShader: this.adaptLuminanceShader.fragmentShader,\n\t\tdefines: this.adaptLuminanceShader.defines,\n\t\tblending: THREE.NoBlending\n\t} );\n\n\tif ( THREE.ToneMapShader === undefined )\n\t\tconsole.error( \"THREE.AdaptiveToneMappingPass relies on THREE.ToneMapShader\" );\n\n\tthis.materialToneMap = new THREE.ShaderMaterial( {\n\n\t\tuniforms: THREE.UniformsUtils.clone( THREE.ToneMapShader.uniforms ),\n\t\tvertexShader: THREE.ToneMapShader.vertexShader,\n\t\tfragmentShader: THREE.ToneMapShader.fragmentShader,\n\t\tblending: THREE.NoBlending\n\t} );\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.AdaptiveToneMappingPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.AdaptiveToneMappingPass.prototype = {\n\n\tconstructor: THREE.AdaptiveToneMappingPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tif ( this.needsInit ) {\n\n\t\t\tthis.reset( renderer );\n\n\t\t\tthis.luminanceRT.texture.type = readBuffer.texture.type;\n\t\t\tthis.previousLuminanceRT.texture.type = readBuffer.texture.type;\n\t\t\tthis.currentLuminanceRT.texture.type = readBuffer.texture.type;\n\t\t\tthis.needsInit = false;\n\n\t\t}\n\n\t\tif ( this.adaptive ) {\n\n\t\t\t//Render the luminance of the current scene into a render target with mipmapping enabled\n\t\t\tthis.quad.material = this.materialLuminance;\n\t\t\tthis.materialLuminance.uniforms.tDiffuse.value = readBuffer;\n\t\t\trenderer.render( this.scene, this.camera, this.currentLuminanceRT );\n\n\t\t\t//Use the new luminance values, the previous luminance and the frame delta to\n\t\t\t//adapt the luminance over time.\n\t\t\tthis.quad.material = this.materialAdaptiveLum;\n\t\t\tthis.materialAdaptiveLum.uniforms.delta.value = delta;\n\t\t\tthis.materialAdaptiveLum.uniforms.lastLum.value = this.previousLuminanceRT;\n\t\t\tthis.materialAdaptiveLum.uniforms.currentLum.value = this.currentLuminanceRT;\n\t\t\trenderer.render( this.scene, this.camera, this.luminanceRT );\n\n\t\t\t//Copy the new adapted luminance value so that it can be used by the next frame.\n\t\t\tthis.quad.material = this.materialCopy;\n\t\t\tthis.copyUniforms.tDiffuse.value = this.luminanceRT;\n\t\t\trenderer.render( this.scene, this.camera, this.previousLuminanceRT );\n\n\t\t}\n\n\t\tthis.quad.material = this.materialToneMap;\n\t\tthis.materialToneMap.uniforms.tDiffuse.value = readBuffer;\n\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t},\n\n\treset: function( renderer ) {\n\n\t\t// render targets\n\t\tif ( this.luminanceRT ) {\n\n\t\t\tthis.luminanceRT.dispose();\n\n\t\t}\n\t\tif ( this.currentLuminanceRT ) {\n\n\t\t\tthis.currentLuminanceRT.dispose();\n\n\t\t}\n\t\tif ( this.previousLuminanceRT ) {\n\n\t\t\tthis.previousLuminanceRT.dispose();\n\n\t\t}\n\n\t\tvar pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; // was RGB format. changed to RGBA format. see discussion in #8415 / #8450\n\n\t\tthis.luminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars );\n\t\tthis.luminanceRT.texture.generateMipmaps = false;\n\n\t\tthis.previousLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars );\n\t\tthis.previousLuminanceRT.texture.generateMipmaps = false;\n\n\t\t// We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader\n\t\tpars.minFilter = THREE.LinearMipMapLinearFilter;\n\t\tthis.currentLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars );\n\n\t\tif ( this.adaptive ) {\n\n\t\t\tthis.materialToneMap.defines[ \"ADAPTED_LUMINANCE\" ] = \"\";\n\t\t\tthis.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT;\n\n\t\t}\n\t\t//Put something in the adaptive luminance texture so that the scene can render initially\n\t\tthis.quad.material = new THREE.MeshBasicMaterial( { color: 0x777777 } );\n\t\tthis.materialLuminance.needsUpdate = true;\n\t\tthis.materialAdaptiveLum.needsUpdate = true;\n\t\tthis.materialToneMap.needsUpdate = true;\n\t\t// renderer.render( this.scene, this.camera, this.luminanceRT );\n\t\t// renderer.render( this.scene, this.camera, this.previousLuminanceRT );\n\t\t// renderer.render( this.scene, this.camera, this.currentLuminanceRT );\n\n\t},\n\n\tsetAdaptive: function( adaptive ) {\n\n\t\tif ( adaptive ) {\n\n\t\t\tthis.adaptive = true;\n\t\t\tthis.materialToneMap.defines[ \"ADAPTED_LUMINANCE\" ] = \"\";\n\t\t\tthis.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT;\n\n\t\t} else {\n\n\t\t\tthis.adaptive = false;\n\t\t\tdelete this.materialToneMap.defines[ \"ADAPTED_LUMINANCE\" ];\n\t\t\tthis.materialToneMap.uniforms.luminanceMap.value = undefined;\n\n\t\t}\n\t\tthis.materialToneMap.needsUpdate = true;\n\n\t},\n\n\tsetAdaptionRate: function( rate ) {\n\n\t\tif ( rate ) {\n\n\t\t\tthis.materialAdaptiveLum.uniforms.tau.value = Math.abs( rate );\n\n\t\t}\n\n\t},\n\n\tsetMaxLuminance: function( maxLum ) {\n\n\t\tif ( maxLum ) {\n\n\t\t\tthis.materialToneMap.uniforms.maxLuminance.value = maxLum;\n\n\t\t}\n\n\t},\n\n\tsetAverageLuminance: function( avgLum ) {\n\n\t\tif ( avgLum ) {\n\n\t\t\tthis.materialToneMap.uniforms.averageLuminance.value = avgLum;\n\n\t\t}\n\n\t},\n\n\tsetMiddleGrey: function( middleGrey ) {\n\n\t\tif ( middleGrey ) {\n\n\t\t\tthis.materialToneMap.uniforms.middleGrey.value = middleGrey;\n\n\t\t}\n\n\t},\n\n\tdispose: function() {\n\n\t\tif ( this.luminanceRT ) {\n\n\t\t\tthis.luminanceRT.dispose();\n\n\t\t}\n\t\tif ( this.previousLuminanceRT ) {\n\n\t\t\tthis.previousLuminanceRT.dispose();\n\n\t\t}\n\t\tif ( this.currentLuminanceRT ) {\n\n\t\t\tthis.currentLuminanceRT.dispose();\n\n\t\t}\n\t\tif ( this.materialLuminance ) {\n\n\t\t\tthis.materialLuminance.dispose();\n\n\t\t}\n\t\tif ( this.materialAdaptiveLum ) {\n\n\t\t\tthis.materialAdaptiveLum.dispose();\n\n\t\t}\n\t\tif ( this.materialCopy ) {\n\n\t\t\tthis.materialCopy.dispose();\n\n\t\t}\n\t\tif ( this.materialToneMap ) {\n\n\t\t\tthis.materialToneMap.dispose();\n\n\t\t}\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/BloomPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.BloomPass = function ( strength, kernelSize, sigma, resolution ) {\n\n\tTHREE.Pass.call( this );\n\n\tstrength = ( strength !== undefined ) ? strength : 1;\n\tkernelSize = ( kernelSize !== undefined ) ? kernelSize : 25;\n\tsigma = ( sigma !== undefined ) ? sigma : 4.0;\n\tresolution = ( resolution !== undefined ) ? resolution : 256;\n\n\t// render targets\n\n\tvar pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };\n\n\tthis.renderTargetX = new THREE.WebGLRenderTarget( resolution, resolution, pars );\n\tthis.renderTargetY = new THREE.WebGLRenderTarget( resolution, resolution, pars );\n\n\t// copy material\n\n\tif ( THREE.CopyShader === undefined )\n\t\tconsole.error( \"THREE.BloomPass relies on THREE.CopyShader\" );\n\n\tvar copyShader = THREE.CopyShader;\n\n\tthis.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );\n\n\tthis.copyUniforms[ \"opacity\" ].value = strength;\n\n\tthis.materialCopy = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.copyUniforms,\n\t\tvertexShader: copyShader.vertexShader,\n\t\tfragmentShader: copyShader.fragmentShader,\n\t\tblending: THREE.AdditiveBlending,\n\t\ttransparent: true\n\n\t} );\n\n\t// convolution material\n\n\tif ( THREE.ConvolutionShader === undefined )\n\t\tconsole.error( \"THREE.BloomPass relies on THREE.ConvolutionShader\" );\n\n\tvar convolutionShader = THREE.ConvolutionShader;\n\n\tthis.convolutionUniforms = THREE.UniformsUtils.clone( convolutionShader.uniforms );\n\n\tthis.convolutionUniforms[ \"uImageIncrement\" ].value = THREE.BloomPass.blurX;\n\tthis.convolutionUniforms[ \"cKernel\" ].value = THREE.ConvolutionShader.buildKernel( sigma );\n\n\tthis.materialConvolution = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.convolutionUniforms,\n\t\tvertexShader:  convolutionShader.vertexShader,\n\t\tfragmentShader: convolutionShader.fragmentShader,\n\t\tdefines: {\n\t\t\t\"KERNEL_SIZE_FLOAT\": kernelSize.toFixed( 1 ),\n\t\t\t\"KERNEL_SIZE_INT\": kernelSize.toFixed( 0 )\n\t\t}\n\n\t} );\n\n\tthis.needsSwap = false;\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.BloomPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.BloomPass.prototype = {\n\n\tconstructor: THREE.BloomPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tif ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );\n\n\t\t// Render quad with blured scene into texture (convolution pass 1)\n\n\t\tthis.quad.material = this.materialConvolution;\n\n\t\tthis.convolutionUniforms[ \"tDiffuse\" ].value = readBuffer;\n\t\tthis.convolutionUniforms[ \"uImageIncrement\" ].value = THREE.BloomPass.blurX;\n\n\t\trenderer.render( this.scene, this.camera, this.renderTargetX, true );\n\n\n\t\t// Render quad with blured scene into texture (convolution pass 2)\n\n\t\tthis.convolutionUniforms[ \"tDiffuse\" ].value = this.renderTargetX;\n\t\tthis.convolutionUniforms[ \"uImageIncrement\" ].value = THREE.BloomPass.blurY;\n\n\t\trenderer.render( this.scene, this.camera, this.renderTargetY, true );\n\n\t\t// Render original scene with superimposed blur to texture\n\n\t\tthis.quad.material = this.materialCopy;\n\n\t\tthis.copyUniforms[ \"tDiffuse\" ].value = this.renderTargetY;\n\n\t\tif ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );\n\n\t\trenderer.render( this.scene, this.camera, readBuffer, this.clear );\n\n\t}\n\n};\n\nTHREE.BloomPass.blurX = new THREE.Vector2( 0.001953125, 0.0 );\nTHREE.BloomPass.blurY = new THREE.Vector2( 0.0, 0.001953125 );\n"
  },
  {
    "path": "example/js/lib/postprocessing/BokehPass.js",
    "content": "/**\n * Depth-of-field post-process with bokeh shader\n */\n\n\nTHREE.BokehPass = function ( scene, camera, params ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.scene = scene;\n\tthis.camera = camera;\n\n\tvar focus = ( params.focus !== undefined ) ? params.focus : 1.0;\n\tvar aspect = ( params.aspect !== undefined ) ? params.aspect : camera.aspect;\n\tvar aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025;\n\tvar maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0;\n\n\t// render targets\n\n\tvar width = params.width || window.innerWidth || 1;\n\tvar height = params.height || window.innerHeight || 1;\n\n\tthis.renderTargetColor = new THREE.WebGLRenderTarget( width, height, {\n\t\tminFilter: THREE.LinearFilter,\n\t\tmagFilter: THREE.LinearFilter,\n\t\tformat: THREE.RGBFormat\n\t} );\n\n\tthis.renderTargetDepth = this.renderTargetColor.clone();\n\n\t// depth material\n\n\tthis.materialDepth = new THREE.MeshDepthMaterial();\n\n\t// bokeh material\n\n\tif ( THREE.BokehShader === undefined ) {\n\n\t\tconsole.error( \"THREE.BokehPass relies on THREE.BokehShader\" );\n\n\t}\n\t\n\tvar bokehShader = THREE.BokehShader;\n\tvar bokehUniforms = THREE.UniformsUtils.clone( bokehShader.uniforms );\n\n\tbokehUniforms[ \"tDepth\" ].value = this.renderTargetDepth;\n\n\tbokehUniforms[ \"focus\" ].value = focus;\n\tbokehUniforms[ \"aspect\" ].value = aspect;\n\tbokehUniforms[ \"aperture\" ].value = aperture;\n\tbokehUniforms[ \"maxblur\" ].value = maxblur;\n\n\tthis.materialBokeh = new THREE.ShaderMaterial( {\n\t\tuniforms: bokehUniforms,\n\t\tvertexShader: bokehShader.vertexShader,\n\t\tfragmentShader: bokehShader.fragmentShader\n\t} );\n\n\tthis.uniforms = bokehUniforms;\n\tthis.needsSwap = false;\n\n\tthis.camera2 = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene2  = new THREE.Scene();\n\n\tthis.quad2 = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene2.add( this.quad2 );\n\n};\n\nTHREE.BokehPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.BokehPass.prototype = {\n\n\tconstructor: THREE.BokehPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.quad2.material = this.materialBokeh;\n\n\t\t// Render depth into texture\n\n\t\tthis.scene.overrideMaterial = this.materialDepth;\n\n\t\trenderer.render( this.scene, this.camera, this.renderTargetDepth, true );\n\n\t\t// Render bokeh composite\n\n\t\tthis.uniforms[ \"tColor\" ].value = readBuffer;\n\n\t\tif ( this.renderToScreen ) {\n\n\t\t\trenderer.render( this.scene2, this.camera2 );\n\n\t\t} else {\n\n\t\t\trenderer.render( this.scene2, this.camera2, writeBuffer, this.clear );\n\n\t\t}\n\n\t\tthis.scene.overrideMaterial = null;\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/ClearPass.js",
    "content": "/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nTHREE.ClearPass = function () {\n\n\tTHREE.Pass.call( this );\n\n\tthis.needsSwap = false;\n\n};\n\nTHREE.ClearPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.ClearPass.prototype = {\n\n\tconstructor: THREE.ClearPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\trenderer.setRenderTarget( readBuffer );\n\t\trenderer.clear();\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/DotScreenPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.DotScreenPass = function ( center, angle, scale ) {\n\n\tTHREE.Pass.call( this );\n\n\tif ( THREE.DotScreenShader === undefined )\n\t\tconsole.error( \"THREE.DotScreenPass relies on THREE.DotScreenShader\" );\n\n\tvar shader = THREE.DotScreenShader;\n\n\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\tif ( center !== undefined ) this.uniforms[ \"center\" ].value.copy( center );\n\tif ( angle !== undefined ) this.uniforms[ \"angle\" ].value = angle;\n\tif ( scale !== undefined ) this.uniforms[ \"scale\" ].value = scale;\n\n\tthis.material = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.uniforms,\n\t\tvertexShader: shader.vertexShader,\n\t\tfragmentShader: shader.fragmentShader\n\n\t} );\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.DotScreenPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.DotScreenPass.prototype = {\n\n\tconstructor: THREE.DotScreenPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.uniforms[ \"tDiffuse\" ].value = readBuffer;\n\t\tthis.uniforms[ \"tSize\" ].value.set( readBuffer.width, readBuffer.height );\n\n\t\tthis.quad.material = this.material;\n\n\t\tif ( this.renderToScreen ) {\n\n\t\t\trenderer.render( this.scene, this.camera );\n\n\t\t} else {\n\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t\t}\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/EffectComposer.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.EffectComposer = function ( renderer, renderTarget ) {\n\n\tthis.renderer = renderer;\n\n\tif ( renderTarget === undefined ) {\n\n\t\tvar parameters = {\n\t\t\tminFilter: THREE.LinearFilter,\n\t\t\tmagFilter: THREE.LinearFilter,\n\t\t\tformat: THREE.RGBAFormat,\n\t\t\tstencilBuffer: false\n\t\t};\n\t\tvar size = renderer.getSize();\n\t\trenderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );\n\n\t}\n\n\tthis.renderTarget1 = renderTarget;\n\tthis.renderTarget2 = renderTarget.clone();\n\n\tthis.writeBuffer = this.renderTarget1;\n\tthis.readBuffer = this.renderTarget2;\n\n\tthis.passes = [];\n\n\tif ( THREE.CopyShader === undefined )\n\t\tconsole.error( \"THREE.EffectComposer relies on THREE.CopyShader\" );\n\n\tthis.copyPass = new THREE.ShaderPass( THREE.CopyShader );\n\n};\n\nTHREE.EffectComposer.prototype = {\n\n\tswapBuffers: function() {\n\n\t\tvar tmp = this.readBuffer;\n\t\tthis.readBuffer = this.writeBuffer;\n\t\tthis.writeBuffer = tmp;\n\n\t},\n\n\taddPass: function ( pass ) {\n\n\t\tthis.passes.push( pass );\n\n\t},\n\n\tinsertPass: function ( pass, index ) {\n\n\t\tthis.passes.splice( index, 0, pass );\n\n\t},\n\n\trender: function ( delta ) {\n\n\t\tthis.writeBuffer = this.renderTarget1;\n\t\tthis.readBuffer = this.renderTarget2;\n\n\t\tvar maskActive = false;\n\n\t\tvar pass, i, il = this.passes.length;\n\n\t\tfor ( i = 0; i < il; i ++ ) {\n\n\t\t\tpass = this.passes[ i ];\n\n\t\t\tif ( ! pass.enabled ) continue;\n\n\t\t\tpass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );\n\n\t\t\tif ( pass.needsSwap ) {\n\n\t\t\t\tif ( maskActive ) {\n\n\t\t\t\t\tvar context = this.renderer.context;\n\n\t\t\t\t\tcontext.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );\n\n\t\t\t\t\tthis.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );\n\n\t\t\t\t\tcontext.stencilFunc( context.EQUAL, 1, 0xffffffff );\n\n\t\t\t\t}\n\n\t\t\t\tthis.swapBuffers();\n\n\t\t\t}\n\n\t\t\tif ( pass instanceof THREE.MaskPass ) {\n\n\t\t\t\tmaskActive = true;\n\n\t\t\t} else if ( pass instanceof THREE.ClearMaskPass ) {\n\n\t\t\t\tmaskActive = false;\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\treset: function ( renderTarget ) {\n\n\t\tif ( renderTarget === undefined ) {\n\n\t\t\tvar size = this.renderer.getSize();\n\n\t\t\trenderTarget = this.renderTarget1.clone();\n\t\t\trenderTarget.setSize( size.width, size.height );\n\n\t\t}\n\n\t\tthis.renderTarget1.dispose();\n\t\tthis.renderTarget2.dispose();\n\t\tthis.renderTarget1 = renderTarget;\n\t\tthis.renderTarget2 = renderTarget.clone();\n\n\t\tthis.writeBuffer = this.renderTarget1;\n\t\tthis.readBuffer = this.renderTarget2;\n\n\t},\n\n\tsetSize: function ( width, height ) {\n\n\t\tthis.renderTarget1.setSize( width, height );\n\t\tthis.renderTarget2.setSize( width, height );\n\n\t}\n\n};\n\n\nTHREE.Pass = function () {\n\n  // if set to true, the pass is processed by the composer\n  this.enabled = true;\n\n  // if set to true, the pass indicates to swap read and write buffer after rendering\n  this.needsSwap = true;\n\n  // if set to true, the pass clears its buffer before rendering\n  this.clear = false;\n\n  // if set to true, the result of the pass is rendered to screen\n  this.renderToScreen = false;\n\n};\n\nTHREE.Pass.prototype = {\n\n  constructor: THREE.Pass,\n\n  render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tconsole.error( \"THREE.Pass: .render() must be implemented in derived pass.\" );\n\n  }\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/FilmPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.FilmPass = function ( noiseIntensity, scanlinesIntensity, scanlinesCount, grayscale ) {\n\n\tTHREE.Pass.call( this );\n\n\tif ( THREE.FilmShader === undefined )\n\t\tconsole.error( \"THREE.FilmPass relies on THREE.FilmShader\" );\n\n\tvar shader = THREE.FilmShader;\n\n\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\tthis.material = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.uniforms,\n\t\tvertexShader: shader.vertexShader,\n\t\tfragmentShader: shader.fragmentShader\n\n\t} );\n\n\tif ( grayscale !== undefined )\tthis.uniforms.grayscale.value = grayscale;\n\tif ( noiseIntensity !== undefined ) this.uniforms.nIntensity.value = noiseIntensity;\n\tif ( scanlinesIntensity !== undefined ) this.uniforms.sIntensity.value = scanlinesIntensity;\n\tif ( scanlinesCount !== undefined ) this.uniforms.sCount.value = scanlinesCount;\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.FilmPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.FilmPass.prototype = {\n\n\tconstructor: THREE.FilmPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.uniforms[ \"tDiffuse\" ].value = readBuffer;\n\t\tthis.uniforms[ \"time\" ].value += delta;\n\n\t\tthis.quad.material = this.material;\n\n\t\tif ( this.renderToScreen ) {\n\n\t\t\trenderer.render( this.scene, this.camera );\n\n\t\t} else {\n\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t\t}\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/GlitchPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.GlitchPass = function ( dt_size ) {\n\n\tTHREE.Pass.call( this );\n\n\tif ( THREE.DigitalGlitch === undefined ) console.error( \"THREE.GlitchPass relies on THREE.DigitalGlitch\" );\n\n\tvar shader = THREE.DigitalGlitch;\n\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\tif ( dt_size == undefined ) dt_size = 64;\n\n\n\tthis.uniforms[ \"tDisp\" ].value = this.generateHeightmap( dt_size );\n\n\n\tthis.material = new THREE.ShaderMaterial( {\n\t\tuniforms: this.uniforms,\n\t\tvertexShader: shader.vertexShader,\n\t\tfragmentShader: shader.fragmentShader\n\t} );\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n\tthis.goWild = false;\n\tthis.curF = 0;\n\tthis.generateTrigger();\n\n};\n\nTHREE.GlitchPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.GlitchPass.prototype = {\n\n\tconstructor: THREE.GlitchPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.uniforms[ \"tDiffuse\" ].value = readBuffer;\n\t\tthis.uniforms[ 'seed' ].value = Math.random();//default seeding\n\t\tthis.uniforms[ 'byp' ].value = 0;\n\n\t\tif ( this.curF % this.randX == 0 || this.goWild == true ) {\n\n\t\t\tthis.uniforms[ 'amount' ].value = Math.random() / 30;\n\t\t\tthis.uniforms[ 'angle' ].value = THREE.Math.randFloat( - Math.PI, Math.PI );\n\t\t\tthis.uniforms[ 'seed_x' ].value = THREE.Math.randFloat( - 1, 1 );\n\t\t\tthis.uniforms[ 'seed_y' ].value = THREE.Math.randFloat( - 1, 1 );\n\t\t\tthis.uniforms[ 'distortion_x' ].value = THREE.Math.randFloat( 0, 1 );\n\t\t\tthis.uniforms[ 'distortion_y' ].value = THREE.Math.randFloat( 0, 1 );\n\t\t\tthis.curF = 0;\n\t\t\tthis.generateTrigger();\n\n\t\t} else if ( this.curF % this.randX < this.randX / 5 ) {\n\n\t\t\tthis.uniforms[ 'amount' ].value = Math.random() / 90;\n\t\t\tthis.uniforms[ 'angle' ].value = THREE.Math.randFloat( - Math.PI, Math.PI );\n\t\t\tthis.uniforms[ 'distortion_x' ].value = THREE.Math.randFloat( 0, 1 );\n\t\t\tthis.uniforms[ 'distortion_y' ].value = THREE.Math.randFloat( 0, 1 );\n\t\t\tthis.uniforms[ 'seed_x' ].value = THREE.Math.randFloat( - 0.3, 0.3 );\n\t\t\tthis.uniforms[ 'seed_y' ].value = THREE.Math.randFloat( - 0.3, 0.3 );\n\n\t\t} else if ( this.goWild == false ) {\n\n\t\t\tthis.uniforms[ 'byp' ].value = 1;\n\n\t\t}\n\n\t\tthis.curF ++;\n\t\tthis.quad.material = this.material;\n\n\t\tif ( this.renderToScreen ) {\n\n\t\t\trenderer.render( this.scene, this.camera );\n\n\t\t} else {\n\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t\t}\n\n\t},\n\n\tgenerateTrigger: function() {\n\n\t\tthis.randX = THREE.Math.randInt( 120, 240 );\n\n\t},\n\n\tgenerateHeightmap: function( dt_size ) {\n\n\t\tvar data_arr = new Float32Array( dt_size * dt_size * 3 );\n\t\tvar length = dt_size * dt_size;\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar val = THREE.Math.randFloat( 0, 1 );\n\t\t\tdata_arr[ i * 3 + 0 ] = val;\n\t\t\tdata_arr[ i * 3 + 1 ] = val;\n\t\t\tdata_arr[ i * 3 + 2 ] = val;\n\n\t\t}\n\n\t\tvar texture = new THREE.DataTexture( data_arr, dt_size, dt_size, THREE.RGBFormat, THREE.FloatType );\n\t\ttexture.needsUpdate = true;\n\t\treturn texture;\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/ManualMSAARenderPass.js",
    "content": "/**\n*\n* Manual Multi-Sample Anti-Aliasing Render Pass\n*\n* @author bhouston / http://clara.io/\n*\n* This manual approach to MSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.\n*\n* References: https://en.wikipedia.org/wiki/Multisample_anti-aliasing\n*\n*/\n\nTHREE.ManualMSAARenderPass = function ( scene, camera, params ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.scene = scene;\n\tthis.camera = camera;\n\n\tthis.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.\n\n\tthis.params = params || { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };\n\tthis.params.minFilter = THREE.NearestFilter;\n\tthis.params.maxFilter = THREE.NearestFilter;\n\n\tif ( THREE.CompositeShader === undefined ) {\n\n\t\tconsole.error( \"THREE.ManualMSAARenderPass relies on THREE.CompositeShader\" );\n\n\t}\n\n\tvar compositeShader = THREE.CompositeShader;\n\tthis.compositeUniforms = THREE.UniformsUtils.clone( compositeShader.uniforms );\n\n\tthis.materialComposite = new THREE.ShaderMaterial(\t{\n\n\t\tuniforms: this.compositeUniforms,\n\t\tvertexShader: compositeShader.vertexShader,\n\t\tfragmentShader: compositeShader.fragmentShader,\n\t\ttransparent: true,\n\t\tblending: THREE.CustomBlending,\n\t\tblendSrc: THREE.OneFactor,\n\t\tblendDst: THREE.OneFactor,\n\t\tblendSrcAlpha: THREE.OneFactor,\n\t\tblendDstAlpha: THREE.OneFactor,\n\t\tblendEquation: THREE.AddEquation,\n\t\tdepthTest: false,\n\t\tdepthWrite: false\n\n\t} );\n\n\tthis.camera2 = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene2\t= new THREE.Scene();\n\tthis.quad2 = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), this.materialComposite );\n\tthis.scene2.add( this.quad2 );\n\n};\n\nTHREE.ManualMSAARenderPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.ManualMSAARenderPass.prototype = {\n\n\tconstructor: THREE.ManualMSAARenderPass,\n\n\tdispose: function() {\n\n\t\tif ( this.sampleRenderTarget ) {\n\n\t\t\tthis.sampleRenderTarget.dispose();\n\t\t\tthis.sampleRenderTarget = null;\n\n\t\t}\n\n\t},\n\n\n\tsetSize: function ( width, height ) {\n\n\t\tthis.sampleRenderTarget.setSize( width, height );\n\n\t},\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tvar camera = ( this.camera || this.scene.camera );\n\t\tvar jitterOffsets = THREE.ManualMSAARenderPass.JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];\n\n\t\tif( jitterOffsets.length === 1 ) {\n\n\t\t\trenderer.render( this.scene, camera, writeBuffer, true );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( ! this.sampleRenderTarget ) {\n\n\t\t\tthis.sampleRenderTarget = new THREE.WebGLRenderTarget( readBuffer.width, readBuffer.height, this.params );\n\n\t\t}\n\n\t\tvar autoClear = renderer.autoClear;\n\t\trenderer.autoClear = false;\n\n\t\tthis.compositeUniforms[ \"scale\" ].value = 1.0 / ( jitterOffsets.length );\n\t\tthis.compositeUniforms[ \"tForeground\" ].value = this.sampleRenderTarget;\n\n\t\t// render the scene multiple times, each slightly jitter offset from the last and accumulate the results.\n\t\tfor ( var i = 0; i < jitterOffsets.length; i ++ ) {\n\n\t\t\t// only jitters perspective cameras.\tTODO: add support for jittering orthogonal cameras\n\t\t\tvar jitterOffset = jitterOffsets[i];\n\t\t\tif ( camera.setViewOffset ) {\n\t\t\t\tcamera.setViewOffset( readBuffer.width, readBuffer.height,\n\t\t\t\t\tjitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625,   // 0.0625 = 1 / 16\n\t\t\t\t\treadBuffer.width, readBuffer.height );\n\t\t\t}\n\n\t\t\trenderer.render( this.scene, this.camera, this.sampleRenderTarget, true );\n\t\t\trenderer.render( this.scene2, this.camera2, writeBuffer, ( i === 0 ) );\n\n\t\t}\n\n\t\t// reset jitter to nothing.\tTODO: add support for orthogonal cameras\n\t\tif ( camera.setViewOffset ) camera.setViewOffset( undefined, undefined, undefined, undefined, undefined, undefined );\n\n\t\trenderer.autoClear = true;\n\n\t}\n\n};\n\n// These jitter vectors are specified in integers because it is easier.\n// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)\n// before being used, thus these integers need to be scaled by 1/16.\n//\n// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396\nTHREE.ManualMSAARenderPass.JitterVectors = [\n\t[\n\t\t[ 0, 0 ]\n\t],\n\t[\n\t\t[ 4, 4 ], [ - 4, - 4 ]\n\t],\n\t[\n\t\t[ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]\n\t],\n\t[\n\t\t[ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ],\n\t\t[ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]\n\t],\n\t[\n\t\t[ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ],\n\t\t[ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ],\n\t\t[ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ],\n\t\t[ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]\n\t],\n\t[\n\t\t[ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ],\n\t\t[ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ],\n\t\t[ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ],\n\t\t[ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ],\n\t\t[ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ],\n\t\t[ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ],\n\t\t[ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],\n\t\t[ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]\n\t]\n];\n"
  },
  {
    "path": "example/js/lib/postprocessing/MaskPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.MaskPass = function ( scene, camera ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.scene = scene;\n\tthis.camera = camera;\n\n\tthis.clear = true;\n\tthis.needsSwap = false;\n\n\tthis.inverse = false;\n\n};\n\nTHREE.MaskPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.MaskPass.prototype = {\n\n\tconstructor: THREE.MaskPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tvar context = renderer.context;\n\n\t\t// don't update color or depth\n\n\t\tcontext.colorMask( false, false, false, false );\n\t\tcontext.depthMask( false );\n\n\t\t// set up stencil\n\n\t\tvar writeValue, clearValue;\n\n\t\tif ( this.inverse ) {\n\n\t\t\twriteValue = 0;\n\t\t\tclearValue = 1;\n\n\t\t} else {\n\n\t\t\twriteValue = 1;\n\t\t\tclearValue = 0;\n\n\t\t}\n\n\t\tcontext.enable( context.STENCIL_TEST );\n\t\tcontext.stencilOp( context.REPLACE, context.REPLACE, context.REPLACE );\n\t\tcontext.stencilFunc( context.ALWAYS, writeValue, 0xffffffff );\n\t\tcontext.clearStencil( clearValue );\n\n\t\t// draw into the stencil buffer\n\n\t\trenderer.render( this.scene, this.camera, readBuffer, this.clear );\n\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t\t// re-enable update of color and depth\n\n\t\tcontext.colorMask( true, true, true, true );\n\t\tcontext.depthMask( true );\n\n\t\t// only render where stencil is set to 1\n\n\t\tcontext.stencilFunc( context.EQUAL, 1, 0xffffffff );  // draw if == 1\n\t\tcontext.stencilOp( context.KEEP, context.KEEP, context.KEEP );\n\n\t}\n\n};\n\n\nTHREE.ClearMaskPass = function () {\n\n\tTHREE.Pass.call( this );\n\n\tthis.needsSwap = false;\n\n};\n\nTHREE.ClearMaskPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.ClearMaskPass.prototype = {\n\n\tconstructor: THREE.ClearMaskPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tvar context = renderer.context;\n\n\t\tcontext.disable( context.STENCIL_TEST );\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/RenderPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.RenderPass = function ( scene, camera, overrideMaterial, clearColor, clearAlpha ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.scene = scene;\n\tthis.camera = camera;\n\n\tthis.overrideMaterial = overrideMaterial;\n\n\tthis.clearColor = clearColor;\n\tthis.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 1;\n\n\tthis.oldClearColor = new THREE.Color();\n\tthis.oldClearAlpha = 1;\n\n\tthis.clear = true;\n\tthis.needsSwap = false;\n\n};\n\nTHREE.RenderPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.RenderPass.prototype = {\n\n\tconstructor: THREE.RenderPass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.scene.overrideMaterial = this.overrideMaterial;\n\n\t\tif ( this.clearColor ) {\n\n\t\t\tthis.oldClearColor.copy( renderer.getClearColor() );\n\t\t\tthis.oldClearAlpha = renderer.getClearAlpha();\n\n\t\t\trenderer.setClearColor( this.clearColor, this.clearAlpha );\n\n\t\t}\n\n\t\trenderer.render( this.scene, this.camera, readBuffer, this.clear );\n\n\t\tif ( this.clearColor ) {\n\n\t\t\trenderer.setClearColor( this.oldClearColor, this.oldClearAlpha );\n\n\t\t}\n\n\t\tthis.scene.overrideMaterial = null;\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/SMAAPass.js",
    "content": "/**\r\n * @author mpk / http://polko.me/\r\n */\r\n\r\nTHREE.SMAAPass = function ( width, height ) {\r\n\r\n\tTHREE.Pass.call( this );\r\n\r\n\t// render targets\r\n\r\n\tthis.edgesRT = new THREE.WebGLRenderTarget( width, height, {\r\n\t\tdepthBuffer: false,\r\n\t\tstencilBuffer: false,\r\n\t\tgenerateMipmaps: false,\r\n\t\tminFilter: THREE.LinearFilter,\r\n\t\tformat: THREE.RGBFormat\r\n\t} );\r\n\r\n\tthis.weightsRT = new THREE.WebGLRenderTarget( width, height, {\r\n\t\tdepthBuffer: false,\r\n\t\tstencilBuffer: false,\r\n\t\tgenerateMipmaps: false,\r\n\t\tminFilter: THREE.LinearFilter,\r\n\t\tformat: THREE.RGBAFormat\r\n\t} );\r\n\r\n\t// textures\r\n\r\n\tvar areaTextureImage = new Image();\r\n\tareaTextureImage.src = this.getAreaTexture();\r\n\r\n\tthis.areaTexture = new THREE.Texture();\r\n\tthis.areaTexture.image = areaTextureImage;\r\n\tthis.areaTexture.format = THREE.RGBFormat;\r\n\tthis.areaTexture.minFilter = THREE.LinearFilter;\r\n\tthis.areaTexture.generateMipmaps = false;\r\n\tthis.areaTexture.needsUpdate = true;\r\n\tthis.areaTexture.flipY = false;\r\n\r\n\tvar searchTextureImage = new Image();\r\n\tsearchTextureImage.src = this.getSearchTexture();\r\n\r\n\tthis.searchTexture = new THREE.Texture();\r\n\tthis.searchTexture.image = searchTextureImage;\r\n\tthis.searchTexture.magFilter = THREE.NearestFilter;\r\n\tthis.searchTexture.minFilter = THREE.NearestFilter;\r\n\tthis.searchTexture.generateMipmaps = false;\r\n\tthis.searchTexture.needsUpdate = true;\r\n\tthis.searchTexture.flipY = false;\r\n\r\n\t// materials - pass 1\r\n\r\n\tif ( THREE.SMAAShader === undefined ) {\r\n\t\tconsole.error( \"THREE.SMAAPass relies on THREE.SMAAShader\" );\r\n\t}\r\n\r\n\tthis.uniformsEdges = THREE.UniformsUtils.clone( THREE.SMAAShader[0].uniforms );\r\n\r\n\tthis.uniformsEdges[ \"resolution\" ].value.set( 1 / width, 1 / height );\r\n\r\n\tthis.materialEdges = new THREE.ShaderMaterial( {\r\n\t\tdefines: THREE.SMAAShader[0].defines,\r\n\t\tuniforms: this.uniformsEdges,\r\n\t\tvertexShader: THREE.SMAAShader[0].vertexShader,\r\n\t\tfragmentShader: THREE.SMAAShader[0].fragmentShader\r\n\t} );\r\n\r\n\t// materials - pass 2\r\n\r\n\tthis.uniformsWeights = THREE.UniformsUtils.clone( THREE.SMAAShader[1].uniforms );\r\n\r\n\tthis.uniformsWeights[ \"resolution\" ].value.set( 1 / width, 1 / height );\r\n\tthis.uniformsWeights[ \"tDiffuse\" ].value = this.edgesRT;\r\n\tthis.uniformsWeights[ \"tArea\" ].value = this.areaTexture;\r\n\tthis.uniformsWeights[ \"tSearch\" ].value = this.searchTexture;\r\n\r\n\tthis.materialWeights = new THREE.ShaderMaterial( {\r\n\t\tdefines: THREE.SMAAShader[1].defines,\r\n\t\tuniforms: this.uniformsWeights,\r\n\t\tvertexShader: THREE.SMAAShader[1].vertexShader,\r\n\t\tfragmentShader: THREE.SMAAShader[1].fragmentShader\r\n\t} );\r\n\r\n\t// materials - pass 3\r\n\r\n\tthis.uniformsBlend = THREE.UniformsUtils.clone( THREE.SMAAShader[2].uniforms );\r\n\r\n\tthis.uniformsBlend[ \"resolution\" ].value.set( 1 / width, 1 / height );\r\n\tthis.uniformsBlend[ \"tDiffuse\" ].value = this.weightsRT;\r\n\r\n\tthis.materialBlend = new THREE.ShaderMaterial( {\r\n\t\tuniforms: this.uniformsBlend,\r\n\t\tvertexShader: THREE.SMAAShader[2].vertexShader,\r\n\t\tfragmentShader: THREE.SMAAShader[2].fragmentShader\r\n\t} );\r\n\r\n\tthis.needsSwap = false;\r\n\r\n\tthis.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );\r\n\tthis.scene  = new THREE.Scene();\r\n\r\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\r\n\tthis.scene.add( this.quad );\r\n\r\n};\r\n\r\nTHREE.SMAAPass.prototype = Object.create( THREE.Pass.prototype );\r\n\r\nTHREE.SMAAPass.prototype = {\r\n\r\n\tconstructor: THREE.SMAAPass,\r\n\r\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\r\n\r\n\t\t// pass 1\r\n\r\n\t\tthis.uniformsEdges[ \"tDiffuse\" ].value = readBuffer;\r\n\r\n\t\tthis.quad.material = this.materialEdges;\r\n\r\n\t\trenderer.render( this.scene, this.camera, this.edgesRT, this.clear );\r\n\r\n\t\t// pass 2\r\n\r\n\t\tthis.quad.material = this.materialWeights;\r\n\r\n\t\trenderer.render( this.scene, this.camera, this.weightsRT, this.clear );\r\n\r\n\t\t// pass 3\r\n\r\n\t\tthis.uniformsBlend[ \"tColor\" ].value = readBuffer;\r\n\r\n\t\tthis.quad.material = this.materialBlend;\r\n\r\n\t\tif ( this.renderToScreen ) {\r\n\r\n\t\t\trenderer.render( this.scene, this.camera );\r\n\r\n\t\t} else {\r\n\r\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tsetSize: function ( width, height ) {\r\n\r\n\t\tthis.edgesRT.setSize( width, height );\r\n\t\tthis.weightsRT.setSize( width, height );\r\n\r\n\t\tthis.materialEdges.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );\r\n\t\tthis.materialWeights.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );\r\n\t\tthis.materialBlend.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );\r\n\r\n\t},\r\n\r\n\tgetAreaTexture: function () {\r\n\t\treturn 'data:image/png;base64,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';\r\n\t},\r\n\r\n\tgetSearchTexture: function () {\r\n\t\treturn 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEIAAAAhCAAAAABIXyLAAAAAOElEQVRIx2NgGAWjYBSMglEwEICREYRgFBZBqDCSLA2MGPUIVQETE9iNUAqLR5gIeoQKRgwXjwAAGn4AtaFeYLEAAAAASUVORK5CYII=';\r\n\t}\r\n\r\n};\r\n"
  },
  {
    "path": "example/js/lib/postprocessing/SavePass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.SavePass = function ( renderTarget ) {\n\n\tTHREE.Pass.call( this );\n\n\tif ( THREE.CopyShader === undefined )\n\t\tconsole.error( \"THREE.SavePass relies on THREE.CopyShader\" );\n\n\tvar shader = THREE.CopyShader;\n\n\tthis.textureID = \"tDiffuse\";\n\n\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\tthis.material = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.uniforms,\n\t\tvertexShader: shader.vertexShader,\n\t\tfragmentShader: shader.fragmentShader\n\n\t} );\n\n\tthis.renderTarget = renderTarget;\n\n\tif ( this.renderTarget === undefined ) {\n\n\t\tthis.renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };\n\t\tthis.renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, this.renderTargetParameters );\n\n\t}\n\n\tthis.needsSwap = false;\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.SavePass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.SavePass.prototype = {\n\n\tconstructor: THREE.SavePass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tif ( this.uniforms[ this.textureID ] ) {\n\n\t\t\tthis.uniforms[ this.textureID ].value = readBuffer;\n\n\t\t}\n\n\t\tthis.quad.material = this.material;\n\n\t\trenderer.render( this.scene, this.camera, this.renderTarget, this.clear );\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/ShaderPass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.ShaderPass = function( shader, textureID ) {\n\n\tTHREE.Pass.call( this );\n\n\tthis.textureID = ( textureID !== undefined ) ? textureID : \"tDiffuse\";\n\n\tif ( shader instanceof THREE.ShaderMaterial ) {\n\n\t\tthis.uniforms = shader.uniforms;\n\n\t\tthis.material = shader;\n\n\t}\n\telse if ( shader ) {\n\n\t\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\t\tthis.material = new THREE.ShaderMaterial( {\n\n\t\t\tdefines: shader.defines || {},\n\t\t\tuniforms: this.uniforms,\n\t\t\tvertexShader: shader.vertexShader,\n\t\t\tfragmentShader: shader.fragmentShader\n\n\t\t} );\n\n\t}\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.ShaderPass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.ShaderPass.prototype = {\n\n\tconstructor: THREE.ShaderPass,\n\n\trender: function( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tif ( this.uniforms[ this.textureID ] ) {\n\n\t\t\tthis.uniforms[ this.textureID ].value = readBuffer;\n\n\t\t}\n\n\t\tthis.quad.material = this.material;\n\n\t\tif ( this.renderToScreen ) {\n\n\t\t\trenderer.render( this.scene, this.camera );\n\n\t\t} else {\n\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, this.clear );\n\n\t\t}\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/postprocessing/TAARenderPass.js",
    "content": "/**\n *\n * Temporal Anti-Aliasing Render Pass\n *\n * @author bhouston / http://clara.io/\n *\n * When there is no motion in the scene, the TAA render pass accumulates jittered camera samples across frames to create a high quality anti-aliased result.\n *\n * References:\n *\n * TODO: Add support for motion vector pas so that accumulation of samples across frames can occur on dynamics scenes.\n *\n */\n\nTHREE.TAARenderPass = function ( scene, camera, params ) {\n\n\tif ( THREE.ManualMSAARenderPass === undefined ) {\n\n\t\tconsole.error( \"THREE.TAARenderPass relies on THREE.ManualMSAARenderPass\" );\n\n\t}\n\tTHREE.ManualMSAARenderPass.call( this, scene, camera, params );\n\n\tthis.sampleLevel = 0;\n\tthis.accumulate = false;\n\n};\n\nTHREE.TAARenderPass.prototype = Object.create( THREE.ManualMSAARenderPass.prototype );\nTHREE.TAARenderPass.prototype.constructor = THREE.TAARenderPass;\nTHREE.TAARenderPass.JitterVectors = THREE.ManualMSAARenderPass.JitterVectors;\n\nTHREE.TAARenderPass.prototype.render = function ( renderer, writeBuffer, readBuffer, delta ) {\n\n\tif( ! this.accumulate ) {\n\n\t\t\tTHREE.ManualMSAARenderPass.prototype.render.call( this, renderer, writeBuffer, readBuffer, delta );\n\n\t\t\tthis.accumulateIndex = -1;\n\t\t\treturn;\n\n\t}\n\n\tvar jitterOffsets = THREE.TAARenderPass.JitterVectors[ 5 ];\n\n\tvar camera = ( this.camera || this.scene.camera );\n\n\tif ( ! this.sampleRenderTarget ) {\n\n\t\tthis.sampleRenderTarget = new THREE.WebGLRenderTarget( readBuffer.width, readBuffer.height, this.params );\n\n\t}\n\n\tif ( ! this.holdRenderTarget ) {\n\n\t\tthis.holdRenderTarget = new THREE.WebGLRenderTarget( readBuffer.width, readBuffer.height, this.params );\n\n\t}\n\n\tif( this.accumulate && this.accumulateIndex === -1 ) {\n\n\t\t\tTHREE.ManualMSAARenderPass.prototype.render.call( this, renderer, this.holdRenderTarget, readBuffer, delta );\n\n\t\t\tthis.accumulateIndex = 0;\n\n\t}\n\n\tvar autoClear = renderer.autoClear;\n\trenderer.autoClear = false;\n\n\tvar sampleWeight = 1.0 / ( jitterOffsets.length );\n\n\tif( this.accumulateIndex >= 0 && this.accumulateIndex < jitterOffsets.length ) {\n\n\t\tthis.compositeUniforms[ \"scale\" ].value = sampleWeight;\n\t\tthis.compositeUniforms[ \"tForeground\" ].value = writeBuffer;\n\n\t\t// render the scene multiple times, each slightly jitter offset from the last and accumulate the results.\n\t\tvar numSamplesPerFrame = Math.pow( 2, this.sampleLevel );\n\t\tfor ( var i = 0; i < numSamplesPerFrame; i ++ ) {\n\n\t\t\tvar j = this.accumulateIndex;\n\t\t\t// only jitters perspective cameras.\tTODO: add support for jittering orthogonal cameras\n\t\t\tvar jitterOffset = jitterOffsets[j];\n\t\t\tif ( camera.setViewOffset ) {\n\t\t\t\tcamera.setViewOffset( readBuffer.width, readBuffer.height,\n\t\t\t\t\tjitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625,   // 0.0625 = 1 / 16\n\t\t\t\t\treadBuffer.width, readBuffer.height );\n\t\t\t}\n\n\t\t\trenderer.render( this.scene, this.camera, writeBuffer, true );\n\n\t\t\trenderer.render( this.scene2, this.camera2, this.sampleRenderTarget, ( this.accumulateIndex === 0 ) );\n\n\t\t\tthis.accumulateIndex ++;\n\t\t\tif( this.accumulateIndex >= jitterOffsets.length ) break;\n\t\t}\n\n\t\t// reset jitter to nothing.\tTODO: add support for orthogonal cameras\n\t\tif ( camera.setViewOffset ) camera.setViewOffset( undefined, undefined, undefined, undefined, undefined, undefined );\n\n\t}\n\n\tvar accumulationWeight = this.accumulateIndex * sampleWeight;\n\n\tif( accumulationWeight > 0 ) {\n\t\tthis.compositeUniforms[ \"scale\" ].value = 1.0;\n\t\tthis.compositeUniforms[ \"tForeground\" ].value = this.sampleRenderTarget;\n\t\trenderer.render( this.scene2, this.camera2, writeBuffer, true );\n\t}\n\n\tif( accumulationWeight < 1.0 ) {\n\t\tthis.compositeUniforms[ \"scale\" ].value = 1.0 - accumulationWeight;\n\t\tthis.compositeUniforms[ \"tForeground\" ].value = this.holdRenderTarget;\n\t\trenderer.render( this.scene2, this.camera2, writeBuffer, ( accumulationWeight === 0 ) );\n\t}\n\n\trenderer.autoClear = autoClear;\n\n\n}\n"
  },
  {
    "path": "example/js/lib/postprocessing/TexturePass.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nTHREE.TexturePass = function ( texture, opacity ) {\n\n\tTHREE.Pass.call( this );\n\n\tif ( THREE.CopyShader === undefined )\n\t\tconsole.error( \"THREE.TexturePass relies on THREE.CopyShader\" );\n\n\tvar shader = THREE.CopyShader;\n\n\tthis.uniforms = THREE.UniformsUtils.clone( shader.uniforms );\n\n\tthis.uniforms[ \"opacity\" ].value = ( opacity !== undefined ) ? opacity : 1.0;\n\tthis.uniforms[ \"tDiffuse\" ].value = texture;\n\n\tthis.material = new THREE.ShaderMaterial( {\n\n\t\tuniforms: this.uniforms,\n\t\tvertexShader: shader.vertexShader,\n\t\tfragmentShader: shader.fragmentShader\n\n\t} );\n\n\tthis.needsSwap = false;\n\n\tthis.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\n\tthis.scene  = new THREE.Scene();\n\n\tthis.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );\n\tthis.scene.add( this.quad );\n\n};\n\nTHREE.TexturePass.prototype = Object.create( THREE.Pass.prototype );\n\nTHREE.TexturePass.prototype = {\n\n\tconstructor: THREE.TexturePass,\n\n\trender: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {\n\n\t\tthis.quad.material = this.material;\n\n\t\trenderer.render( this.scene, this.camera, readBuffer, this.clear );\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BasicShader.js",
    "content": "/**\n * @author mrdoob / http://www.mrdoob.com\n *\n * Simple test shader\n */\n\nTHREE.BasicShader = {\n\n\tuniforms: {},\n\n\tvertexShader: [\n\n\t\t\"void main() {\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"void main() {\",\n\n\t\t\t\"gl_FragColor = vec4( 1.0, 0.0, 0.0, 0.1 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BleachBypassShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Bleach bypass shader [http://en.wikipedia.org/wiki/Bleach_bypass]\n * - based on Nvidia example\n * http://developer.download.nvidia.com/shaderlibrary/webpages/shader_library.html#post_bleach_bypass\n */\n\nTHREE.BleachBypassShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"opacity\":  { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float opacity;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 base = texture2D( tDiffuse, vUv );\",\n\n\t\t\t\"vec3 lumCoeff = vec3( 0.25, 0.65, 0.1 );\",\n\t\t\t\"float lum = dot( lumCoeff, base.rgb );\",\n\t\t\t\"vec3 blend = vec3( lum );\",\n\n\t\t\t\"float L = min( 1.0, max( 0.0, 10.0 * ( lum - 0.45 ) ) );\",\n\n\t\t\t\"vec3 result1 = 2.0 * base.rgb * blend;\",\n\t\t\t\"vec3 result2 = 1.0 - 2.0 * ( 1.0 - blend ) * ( 1.0 - base.rgb );\",\n\n\t\t\t\"vec3 newColor = mix( result1, result2, L );\",\n\n\t\t\t\"float A2 = opacity * base.a;\",\n\t\t\t\"vec3 mixRGB = A2 * newColor.rgb;\",\n\t\t\t\"mixRGB += ( ( 1.0 - A2 ) * base.rgb );\",\n\n\t\t\t\"gl_FragColor = vec4( mixRGB, base.a );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BlendShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Blend two textures\n */\n\nTHREE.BlendShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse1\": { type: \"t\", value: null },\n\t\t\"tDiffuse2\": { type: \"t\", value: null },\n\t\t\"mixRatio\":  { type: \"f\", value: 0.5 },\n\t\t\"opacity\":   { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float opacity;\",\n\t\t\"uniform float mixRatio;\",\n\n\t\t\"uniform sampler2D tDiffuse1;\",\n\t\t\"uniform sampler2D tDiffuse2;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 texel1 = texture2D( tDiffuse1, vUv );\",\n\t\t\t\"vec4 texel2 = texture2D( tDiffuse2, vUv );\",\n\t\t\t\"gl_FragColor = opacity * mix( texel1, texel2, mixRatio );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BokehShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Depth-of-field shader with bokeh\n * ported from GLSL shader by Martins Upitis\n * http://artmartinsh.blogspot.com/2010/02/glsl-lens-blur-filter-with-bokeh.html\n */\n\nTHREE.BokehShader = {\n\n\tuniforms: {\n\n\t\t\"tColor\":   { type: \"t\", value: null },\n\t\t\"tDepth\":   { type: \"t\", value: null },\n\t\t\"focus\":    { type: \"f\", value: 1.0 },\n\t\t\"aspect\":   { type: \"f\", value: 1.0 },\n\t\t\"aperture\": { type: \"f\", value: 0.025 },\n\t\t\"maxblur\":  { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"uniform sampler2D tColor;\",\n\t\t\"uniform sampler2D tDepth;\",\n\n\t\t\"uniform float maxblur;\",  // max blur amount\n\t\t\"uniform float aperture;\", // aperture - bigger values for shallower depth of field\n\n\t\t\"uniform float focus;\",\n\t\t\"uniform float aspect;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 aspectcorrect = vec2( 1.0, aspect );\",\n\n\t\t\t\"vec4 depth1 = texture2D( tDepth, vUv );\",\n\n\t\t\t\"float factor = depth1.x - focus;\",\n\n\t\t\t\"vec2 dofblur = vec2 ( clamp( factor * aperture, -maxblur, maxblur ) );\",\n\n\t\t\t\"vec2 dofblur9 = dofblur * 0.9;\",\n\t\t\t\"vec2 dofblur7 = dofblur * 0.7;\",\n\t\t\t\"vec2 dofblur4 = dofblur * 0.4;\",\n\n\t\t\t\"vec4 col = vec4( 0.0 );\",\n\n\t\t\t\"col += texture2D( tColor, vUv.xy );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,   0.4  ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.15,  0.37 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29,  0.29 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.37,  0.15 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.40,  0.0  ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.37, -0.15 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29, -0.29 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,  -0.4  ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.15,  0.37 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29,  0.29 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.37,  0.15 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.4,   0.0  ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.15, -0.37 ) * aspectcorrect ) * dofblur );\",\n\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.15,  0.37 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.37,  0.15 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.37, -0.15 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.15, -0.37 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.15,  0.37 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.37,  0.15 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.37, -0.15 ) * aspectcorrect ) * dofblur9 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.15, -0.37 ) * aspectcorrect ) * dofblur9 );\",\n\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29,  0.29 ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.40,  0.0  ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29, -0.29 ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,  -0.4  ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29,  0.29 ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.4,   0.0  ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur7 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,   0.4  ) * aspectcorrect ) * dofblur7 );\",\n\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29,  0.29 ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.4,   0.0  ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.29, -0.29 ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,  -0.4  ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29,  0.29 ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.4,   0.0  ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2( -0.29, -0.29 ) * aspectcorrect ) * dofblur4 );\",\n\t\t\t\"col += texture2D( tColor, vUv.xy + ( vec2(  0.0,   0.4  ) * aspectcorrect ) * dofblur4 );\",\n\n\t\t\t\"gl_FragColor = col / 41.0;\",\n\t\t\t\"gl_FragColor.a = 1.0;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BokehShader2.js",
    "content": "/**\n * @author zz85 / https://github.com/zz85 | twitter.com/blurspline\n *\n * Depth-of-field shader with bokeh\n * ported from GLSL shader by Martins Upitis\n * http://blenderartists.org/forum/showthread.php?237488-GLSL-depth-of-field-with-bokeh-v2-4-(update)\n *\n * Requires #define RINGS and SAMPLES integers\n */\n\n\n\nTHREE.BokehShader = {\n\n\tuniforms: {\n\n\t\t\"textureWidth\":  { type: \"f\", value: 1.0 },\n\t\t\"textureHeight\":  { type: \"f\", value: 1.0 },\n\n\t\t\"focalDepth\":   { type: \"f\", value: 1.0 },\n\t\t\"focalLength\":   { type: \"f\", value: 24.0 },\n\t\t\"fstop\": { type: \"f\", value: 0.9 },\n\n\t\t\"tColor\":   { type: \"t\", value: null },\n\t\t\"tDepth\":   { type: \"t\", value: null },\n\n\t\t\"maxblur\":  { type: \"f\", value: 1.0 },\n\n\t\t\"showFocus\":   { type: \"i\", value: 0 },\n\t\t\"manualdof\":   { type: \"i\", value: 0 },\n\t\t\"vignetting\":   { type: \"i\", value: 0 },\n\t\t\"depthblur\":   { type: \"i\", value: 0 },\n\n\t\t\"threshold\":  { type: \"f\", value: 0.5 },\n\t\t\"gain\":  { type: \"f\", value: 2.0 },\n\t\t\"bias\":  { type: \"f\", value: 0.5 },\n\t\t\"fringe\":  { type: \"f\", value: 0.7 },\n\n\t\t\"znear\":  { type: \"f\", value: 0.1 },\n\t\t\"zfar\":  { type: \"f\", value: 100 },\n\n\t\t\"noise\":  { type: \"i\", value: 1 },\n\t\t\"dithering\":  { type: \"f\", value: 0.0001 },\n\t\t\"pentagon\": { type: \"i\", value: 0 },\n\n\t\t\"shaderFocus\":  { type: \"i\", value: 1 },\n\t\t\"focusCoords\":  { type: \"v2\", value: new THREE.Vector2() },\n\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"#include <common>\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"uniform sampler2D tColor;\",\n\t\t\"uniform sampler2D tDepth;\",\n\t\t\"uniform float textureWidth;\",\n\t\t\"uniform float textureHeight;\",\n\n\t\t\"uniform float focalDepth;  //focal distance value in meters, but you may use autofocus option below\",\n\t\t\"uniform float focalLength; //focal length in mm\",\n\t\t\"uniform float fstop; //f-stop value\",\n\t\t\"uniform bool showFocus; //show debug focus point and focal range (red = focal point, green = focal range)\",\n\n\t\t\"/*\",\n\t\t\"make sure that these two values are the same for your camera, otherwise distances will be wrong.\",\n\t\t\"*/\",\n\n\t\t\"uniform float znear; // camera clipping start\",\n\t\t\"uniform float zfar; // camera clipping end\",\n\n\t\t\"//------------------------------------------\",\n\t\t\"//user variables\",\n\n\t\t\"const int samples = SAMPLES; //samples on the first ring\",\n\t\t\"const int rings = RINGS; //ring count\",\n\n\t\t\"const int maxringsamples = rings * samples;\",\n\n\t\t\"uniform bool manualdof; // manual dof calculation\",\n\t\t\"float ndofstart = 1.0; // near dof blur start\",\n\t\t\"float ndofdist = 2.0; // near dof blur falloff distance\",\n\t\t\"float fdofstart = 1.0; // far dof blur start\",\n\t\t\"float fdofdist = 3.0; // far dof blur falloff distance\",\n\n\t\t\"float CoC = 0.03; //circle of confusion size in mm (35mm film = 0.03mm)\",\n\n\t\t\"uniform bool vignetting; // use optical lens vignetting\",\n\n\t\t\"float vignout = 1.3; // vignetting outer border\",\n\t\t\"float vignin = 0.0; // vignetting inner border\",\n\t\t\"float vignfade = 22.0; // f-stops till vignete fades\",\n\n\t\t\"uniform bool shaderFocus;\",\n\t\t\"// disable if you use external focalDepth value\",\n\n\t\t\"uniform vec2 focusCoords;\",\n\t\t\"// autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right)\",\n\t\t\"// if center of screen use vec2(0.5, 0.5);\",\n\n\t\t\"uniform float maxblur;\",\n\t\t\"//clamp value of max blur (0.0 = no blur, 1.0 default)\",\n\n\t\t\"uniform float threshold; // highlight threshold;\",\n\t\t\"uniform float gain; // highlight gain;\",\n\n\t\t\"uniform float bias; // bokeh edge bias\",\n\t\t\"uniform float fringe; // bokeh chromatic aberration / fringing\",\n\n\t\t\"uniform bool noise; //use noise instead of pattern for sample dithering\",\n\n\t\t\"uniform float dithering;\",\n\n\t\t\"uniform bool depthblur; // blur the depth buffer\",\n\t\t\"float dbsize = 1.25; // depth blur size\",\n\n\t\t\"/*\",\n\t\t\"next part is experimental\",\n\t\t\"not looking good with small sample and ring count\",\n\t\t\"looks okay starting from samples = 4, rings = 4\",\n\t\t\"*/\",\n\n\t\t\"uniform bool pentagon; //use pentagon as bokeh shape?\",\n\t\t\"float feather = 0.4; //pentagon shape feather\",\n\n\t\t\"//------------------------------------------\",\n\n\t\t\"float penta(vec2 coords) {\",\n\t\t\t\"//pentagonal shape\",\n\t\t\t\"float scale = float(rings) - 1.3;\",\n\t\t\t\"vec4  HS0 = vec4( 1.0,         0.0,         0.0,  1.0);\",\n\t\t\t\"vec4  HS1 = vec4( 0.309016994, 0.951056516, 0.0,  1.0);\",\n\t\t\t\"vec4  HS2 = vec4(-0.809016994, 0.587785252, 0.0,  1.0);\",\n\t\t\t\"vec4  HS3 = vec4(-0.809016994,-0.587785252, 0.0,  1.0);\",\n\t\t\t\"vec4  HS4 = vec4( 0.309016994,-0.951056516, 0.0,  1.0);\",\n\t\t\t\"vec4  HS5 = vec4( 0.0        ,0.0         , 1.0,  1.0);\",\n\n\t\t\t\"vec4  one = vec4( 1.0 );\",\n\n\t\t\t\"vec4 P = vec4((coords),vec2(scale, scale));\",\n\n\t\t\t\"vec4 dist = vec4(0.0);\",\n\t\t\t\"float inorout = -4.0;\",\n\n\t\t\t\"dist.x = dot( P, HS0 );\",\n\t\t\t\"dist.y = dot( P, HS1 );\",\n\t\t\t\"dist.z = dot( P, HS2 );\",\n\t\t\t\"dist.w = dot( P, HS3 );\",\n\n\t\t\t\"dist = smoothstep( -feather, feather, dist );\",\n\n\t\t\t\"inorout += dot( dist, one );\",\n\n\t\t\t\"dist.x = dot( P, HS4 );\",\n\t\t\t\"dist.y = HS5.w - abs( P.z );\",\n\n\t\t\t\"dist = smoothstep( -feather, feather, dist );\",\n\t\t\t\"inorout += dist.x;\",\n\n\t\t\t\"return clamp( inorout, 0.0, 1.0 );\",\n\t\t\"}\",\n\n\t\t\"float bdepth(vec2 coords) {\",\n\t\t\t\"// Depth buffer blur\",\n\t\t\t\"float d = 0.0;\",\n\t\t\t\"float kernel[9];\",\n\t\t\t\"vec2 offset[9];\",\n\n\t\t\t\"vec2 wh = vec2(1.0/textureWidth,1.0/textureHeight) * dbsize;\",\n\n\t\t\t\"offset[0] = vec2(-wh.x,-wh.y);\",\n\t\t\t\"offset[1] = vec2( 0.0, -wh.y);\",\n\t\t\t\"offset[2] = vec2( wh.x -wh.y);\",\n\n\t\t\t\"offset[3] = vec2(-wh.x,  0.0);\",\n\t\t\t\"offset[4] = vec2( 0.0,   0.0);\",\n\t\t\t\"offset[5] = vec2( wh.x,  0.0);\",\n\n\t\t\t\"offset[6] = vec2(-wh.x, wh.y);\",\n\t\t\t\"offset[7] = vec2( 0.0,  wh.y);\",\n\t\t\t\"offset[8] = vec2( wh.x, wh.y);\",\n\n\t\t\t\"kernel[0] = 1.0/16.0;   kernel[1] = 2.0/16.0;   kernel[2] = 1.0/16.0;\",\n\t\t\t\"kernel[3] = 2.0/16.0;   kernel[4] = 4.0/16.0;   kernel[5] = 2.0/16.0;\",\n\t\t\t\"kernel[6] = 1.0/16.0;   kernel[7] = 2.0/16.0;   kernel[8] = 1.0/16.0;\",\n\n\n\t\t\t\"for( int i=0; i<9; i++ ) {\",\n\t\t\t\t\"float tmp = texture2D(tDepth, coords + offset[i]).r;\",\n\t\t\t\t\"d += tmp * kernel[i];\",\n\t\t\t\"}\",\n\n\t\t\t\"return d;\",\n\t\t\"}\",\n\n\n\t\t\"vec3 color(vec2 coords,float blur) {\",\n\t\t\t\"//processing the sample\",\n\n\t\t\t\"vec3 col = vec3(0.0);\",\n\t\t\t\"vec2 texel = vec2(1.0/textureWidth,1.0/textureHeight);\",\n\n\t\t\t\"col.r = texture2D(tColor,coords + vec2(0.0,1.0)*texel*fringe*blur).r;\",\n\t\t\t\"col.g = texture2D(tColor,coords + vec2(-0.866,-0.5)*texel*fringe*blur).g;\",\n\t\t\t\"col.b = texture2D(tColor,coords + vec2(0.866,-0.5)*texel*fringe*blur).b;\",\n\n\t\t\t\"vec3 lumcoeff = vec3(0.299,0.587,0.114);\",\n\t\t\t\"float lum = dot(col.rgb, lumcoeff);\",\n\t\t\t\"float thresh = max((lum-threshold)*gain, 0.0);\",\n\t\t\t\"return col+mix(vec3(0.0),col,thresh*blur);\",\n\t\t\"}\",\n\n\t\t\"vec3 debugFocus(vec3 col, float blur, float depth) {\",\n\t\t\t\"float edge = 0.002*depth; //distance based edge smoothing\",\n\t\t\t\"float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0);\",\n\t\t\t\"float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0);\",\n\n\t\t\t\"col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6);\",\n\t\t\t\"col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2);\",\n\n\t\t\t\"return col;\",\n\t\t\"}\",\n\n\t\t\"float linearize(float depth) {\",\n\t\t\t\"return -zfar * znear / (depth * (zfar - znear) - zfar);\",\n\t\t\"}\",\n\n\n\t\t\"float vignette() {\",\n\t\t\t\"float dist = distance(vUv.xy, vec2(0.5,0.5));\",\n\t\t\t\"dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist);\",\n\t\t\t\"return clamp(dist,0.0,1.0);\",\n\t\t\"}\",\n\n\t\t\"float gather(float i, float j, int ringsamples, inout vec3 col, float w, float h, float blur) {\",\n\t\t\t\"float rings2 = float(rings);\",\n\t\t\t\"float step = PI*2.0 / float(ringsamples);\",\n\t\t\t\"float pw = cos(j*step)*i;\",\n\t\t\t\"float ph = sin(j*step)*i;\",\n\t\t\t\"float p = 1.0;\",\n\t\t\t\"if (pentagon) {\",\n\t\t\t\t\"p = penta(vec2(pw,ph));\",\n\t\t\t\"}\",\n\t\t\t\"col += color(vUv.xy + vec2(pw*w,ph*h), blur) * mix(1.0, i/rings2, bias) * p;\",\n\t\t\t\"return 1.0 * mix(1.0, i /rings2, bias) * p;\",\n\t\t\"}\",\n\n\t\t\"void main() {\",\n\t\t\t\"//scene depth calculation\",\n\n\t\t\t\"float depth = linearize(texture2D(tDepth,vUv.xy).x);\",\n\n\t\t\t\"// Blur depth?\",\n\t\t\t\"if (depthblur) {\",\n\t\t\t\t\"depth = linearize(bdepth(vUv.xy));\",\n\t\t\t\"}\",\n\n\t\t\t\"//focal plane calculation\",\n\n\t\t\t\"float fDepth = focalDepth;\",\n\n\t\t\t\"if (shaderFocus) {\",\n\n\t\t\t\t\"fDepth = linearize(texture2D(tDepth,focusCoords).x);\",\n\n\t\t\t\"}\",\n\n\t\t\t\"// dof blur factor calculation\",\n\n\t\t\t\"float blur = 0.0;\",\n\n\t\t\t\"if (manualdof) {\",\n\t\t\t\t\"float a = depth-fDepth; // Focal plane\",\n\t\t\t\t\"float b = (a-fdofstart)/fdofdist; // Far DoF\",\n\t\t\t\t\"float c = (-a-ndofstart)/ndofdist; // Near Dof\",\n\t\t\t\t\"blur = (a>0.0) ? b : c;\",\n\t\t\t\"} else {\",\n\t\t\t\t\"float f = focalLength; // focal length in mm\",\n\t\t\t\t\"float d = fDepth*1000.0; // focal plane in mm\",\n\t\t\t\t\"float o = depth*1000.0; // depth in mm\",\n\n\t\t\t\t\"float a = (o*f)/(o-f);\",\n\t\t\t\t\"float b = (d*f)/(d-f);\",\n\t\t\t\t\"float c = (d-f)/(d*fstop*CoC);\",\n\n\t\t\t\t\"blur = abs(a-b)*c;\",\n\t\t\t\"}\",\n\n\t\t\t\"blur = clamp(blur,0.0,1.0);\",\n\n\t\t\t\"// calculation of pattern for dithering\",\n\n\t\t\t\"vec2 noise = vec2(rand(vUv.xy), rand( vUv.xy + vec2( 0.4, 0.6 ) ) )*dithering*blur;\",\n\n\t\t\t\"// getting blur x and y step factor\",\n\n\t\t\t\"float w = (1.0/textureWidth)*blur*maxblur+noise.x;\",\n\t\t\t\"float h = (1.0/textureHeight)*blur*maxblur+noise.y;\",\n\n\t\t\t\"// calculation of final color\",\n\n\t\t\t\"vec3 col = vec3(0.0);\",\n\n\t\t\t\"if(blur < 0.05) {\",\n\t\t\t\t\"//some optimization thingy\",\n\t\t\t\t\"col = texture2D(tColor, vUv.xy).rgb;\",\n\t\t\t\"} else {\",\n\t\t\t\t\"col = texture2D(tColor, vUv.xy).rgb;\",\n\t\t\t\t\"float s = 1.0;\",\n\t\t\t\t\"int ringsamples;\",\n\n\t\t\t\t\"for (int i = 1; i <= rings; i++) {\",\n\t\t\t\t\t\"/*unboxstart*/\",\n\t\t\t\t\t\"ringsamples = i * samples;\",\n\n\t\t\t\t\t\"for (int j = 0 ; j < maxringsamples ; j++) {\",\n\t\t\t\t\t\t\"if (j >= ringsamples) break;\",\n\t\t\t\t\t\t\"s += gather(float(i), float(j), ringsamples, col, w, h, blur);\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\t\"/*unboxend*/\",\n\t\t\t\t\"}\",\n\n\t\t\t\t\"col /= s; //divide by sample count\",\n\t\t\t\"}\",\n\n\t\t\t\"if (showFocus) {\",\n\t\t\t\t\"col = debugFocus(col, blur, depth);\",\n\t\t\t\"}\",\n\n\t\t\t\"if (vignetting) {\",\n\t\t\t\t\"col *= vignette();\",\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor.rgb = col;\",\n\t\t\t\"gl_FragColor.a = 1.0;\",\n\t\t\"} \"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/BrightnessContrastShader.js",
    "content": "/**\n * @author tapio / http://tapio.github.com/\n *\n * Brightness and contrast adjustment\n * https://github.com/evanw/glfx.js\n * brightness: -1 to 1 (-1 is solid black, 0 is no change, and 1 is solid white)\n * contrast: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)\n */\n\nTHREE.BrightnessContrastShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":   { type: \"t\", value: null },\n\t\t\"brightness\": { type: \"f\", value: 0 },\n\t\t\"contrast\":   { type: \"f\", value: 0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float brightness;\",\n\t\t\"uniform float contrast;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"gl_FragColor = texture2D( tDiffuse, vUv );\",\n\n\t\t\t\"gl_FragColor.rgb += brightness;\",\n\n\t\t\t\"if (contrast > 0.0) {\",\n\t\t\t\t\"gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5;\",\n\t\t\t\"} else {\",\n\t\t\t\t\"gl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5;\",\n\t\t\t\"}\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/ColorCorrectionShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Color correction\n */\n\nTHREE.ColorCorrectionShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"powRGB\":   { type: \"v3\", value: new THREE.Vector3( 2, 2, 2 ) },\n\t\t\"mulRGB\":   { type: \"v3\", value: new THREE.Vector3( 1, 1, 1 ) },\n\t\t\"addRGB\":   { type: \"v3\", value: new THREE.Vector3( 0, 0, 0 ) }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform vec3 powRGB;\",\n\t\t\"uniform vec3 mulRGB;\",\n\t\t\"uniform vec3 addRGB;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\t\t\t\"vec4 tcolor = texture2D( tDiffuse, vUv );\",\n\t\t\t\"tcolor.a=1.0;\",\n\t\t\t\"vec4 color = vec4(1,0,0,.2) ;\",\n\t\t\t\"gl_FragColor = color;\",\n\t\t\t//\"gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/ColorifyShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Colorify shader\n */\n\nTHREE.ColorifyShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"color\":    { type: \"c\", value: new THREE.Color( 0xffffff ) }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform vec3 color;\",\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 texel = texture2D( tDiffuse, vUv );\",\n\n\t\t\t\"vec3 luma = vec3( 0.299, 0.587, 0.114 );\",\n\t\t\t\"float v = dot( texel.xyz, luma );\",\n\n\t\t\t\"gl_FragColor = vec4( v * color, texel.w );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/CompositeShader.js",
    "content": "/**\n * @author bhouston / http://clara.io/\n *\n * Multi-Sample Anti-aliasing shader - for blending together sample buffers\n */\n\nTHREE.CompositeShader = {\n\n\tshaderID: \"composite\",\n\n\tuniforms: {\n\n\t\t\"tForeground\": { type: \"t\", value: null },\n\t\t\"scale\": { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( '\\n' ),\n\n\tfragmentShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"uniform sampler2D tForeground;\",\n\t\t\"uniform float scale;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 foreground = texture2D( tForeground, vUv );\",\n\n\t\t\t\"gl_FragColor = foreground * scale;\",\n\n\t\t\"}\"\n\n\t].join( '\\n' )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/ConvolutionShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Convolution shader\n * ported from o3d sample to WebGL / GLSL\n * http://o3d.googlecode.com/svn/trunk/samples/convolution.html\n */\n\nTHREE.ConvolutionShader = {\n\n\tdefines: {\n\n\t\t\"KERNEL_SIZE_FLOAT\": \"25.0\",\n\t\t\"KERNEL_SIZE_INT\": \"25\",\n\n\t},\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":        { type: \"t\", value: null },\n\t\t\"uImageIncrement\": { type: \"v2\", value: new THREE.Vector2( 0.001953125, 0.0 ) },\n\t\t\"cKernel\":         { type: \"fv1\", value: [] }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"uniform vec2 uImageIncrement;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv - ( ( KERNEL_SIZE_FLOAT - 1.0 ) / 2.0 ) * uImageIncrement;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float cKernel[ KERNEL_SIZE_INT ];\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform vec2 uImageIncrement;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 imageCoord = vUv;\",\n\t\t\t\"vec4 sum = vec4( 0.0, 0.0, 0.0, 0.0 );\",\n\n\t\t\t\"for( int i = 0; i < KERNEL_SIZE_INT; i ++ ) {\",\n\n\t\t\t\t\"sum += texture2D( tDiffuse, imageCoord ) * cKernel[ i ];\",\n\t\t\t\t\"imageCoord += uImageIncrement;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor = sum;\",\n\n\t\t\"}\"\n\n\n\t].join( \"\\n\" ),\n\n\tbuildKernel: function ( sigma ) {\n\n\t\t// We lop off the sqrt(2 * pi) * sigma term, since we're going to normalize anyway.\n\n\t\tfunction gauss( x, sigma ) {\n\n\t\t\treturn Math.exp( - ( x * x ) / ( 2.0 * sigma * sigma ) );\n\n\t\t}\n\n\t\tvar i, values, sum, halfWidth, kMaxKernelSize = 25, kernelSize = 2 * Math.ceil( sigma * 3.0 ) + 1;\n\n\t\tif ( kernelSize > kMaxKernelSize ) kernelSize = kMaxKernelSize;\n\t\thalfWidth = ( kernelSize - 1 ) * 0.5;\n\n\t\tvalues = new Array( kernelSize );\n\t\tsum = 0.0;\n\t\tfor ( i = 0; i < kernelSize; ++ i ) {\n\n\t\t\tvalues[ i ] = gauss( i - halfWidth, sigma );\n\t\t\tsum += values[ i ];\n\n\t\t}\n\n\t\t// normalize the kernel\n\n\t\tfor ( i = 0; i < kernelSize; ++ i ) values[ i ] /= sum;\n\n\t\treturn values;\n\n\t}\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/CopyShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Full-screen textured quad shader\n */\n\nTHREE.CopyShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"opacity\":  { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float opacity;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 texel = texture2D( tDiffuse, vUv );\",\n\t\t\t\"gl_FragColor = opacity * texel;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/DOFMipMapShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Depth-of-field shader using mipmaps\n * - from Matt Handley @applmak\n * - requires power-of-2 sized render target with enabled mipmaps\n */\n\nTHREE.DOFMipMapShader = {\n\n\tuniforms: {\n\n\t\t\"tColor\":   { type: \"t\", value: null },\n\t\t\"tDepth\":   { type: \"t\", value: null },\n\t\t\"focus\":    { type: \"f\", value: 1.0 },\n\t\t\"maxblur\":  { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float focus;\",\n\t\t\"uniform float maxblur;\",\n\n\t\t\"uniform sampler2D tColor;\",\n\t\t\"uniform sampler2D tDepth;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 depth = texture2D( tDepth, vUv );\",\n\n\t\t\t\"float factor = depth.x - focus;\",\n\n\t\t\t\"vec4 col = texture2D( tColor, vUv, 2.0 * maxblur * abs( focus - depth.x ) );\",\n\n\t\t\t\"gl_FragColor = col;\",\n\t\t\t\"gl_FragColor.a = 1.0;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/DigitalGlitch.js",
    "content": "/**\n * @author felixturner / http://airtight.cc/\n *\n * RGB Shift Shader\n * Shifts red and blue channels from center in opposite directions\n * Ported from http://kriss.cx/tom/2009/05/rgb-shift/\n * by Tom Butterworth / http://kriss.cx/tom/\n *\n * amount: shift distance (1 is width of input)\n * angle: shift angle in radians\n */\n\nTHREE.DigitalGlitch = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":\t\t{ type: \"t\", value: null },//diffuse texture\n\t\t\"tDisp\":\t\t{ type: \"t\", value: null },//displacement texture for digital glitch squares\n\t\t\"byp\":\t\t\t{ type: \"i\", value: 0 },//apply the glitch ?\n\t\t\"amount\":\t\t{ type: \"f\", value: 0.08 },\n\t\t\"angle\":\t\t{ type: \"f\", value: 0.02 },\n\t\t\"seed\":\t\t\t{ type: \"f\", value: 0.02 },\n\t\t\"seed_x\":\t\t{ type: \"f\", value: 0.02 },//-1,1\n\t\t\"seed_y\":\t\t{ type: \"f\", value: 0.02 },//-1,1\n\t\t\"distortion_x\":\t{ type: \"f\", value: 0.5 },\n\t\t\"distortion_y\":\t{ type: \"f\", value: 0.6 },\n\t\t\"col_s\":\t\t{ type: \"f\", value: 0.05 }\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\t\t\"void main() {\",\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\t\t\"}\"\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\t\t\"uniform int byp;\",//should we apply the glitch ?\n\t\t\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform sampler2D tDisp;\",\n\t\t\n\t\t\"uniform float amount;\",\n\t\t\"uniform float angle;\",\n\t\t\"uniform float seed;\",\n\t\t\"uniform float seed_x;\",\n\t\t\"uniform float seed_y;\",\n\t\t\"uniform float distortion_x;\",\n\t\t\"uniform float distortion_y;\",\n\t\t\"uniform float col_s;\",\n\t\t\t\n\t\t\"varying vec2 vUv;\",\n\t\t\n\t\t\n\t\t\"float rand(vec2 co){\",\n\t\t\t\"return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\",\n\t\t\"}\",\n\t\t\t\t\n\t\t\"void main() {\",\n\t\t\t\"if(byp<1) {\",\n\t\t\t\t\"vec2 p = vUv;\",\n\t\t\t\t\"float xs = floor(gl_FragCoord.x / 0.5);\",\n\t\t\t\t\"float ys = floor(gl_FragCoord.y / 0.5);\",\n\t\t\t\t//based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch\n\t\t\t\t\"vec4 normal = texture2D (tDisp, p*seed*seed);\",\n\t\t\t\t\"if(p.y<distortion_x+col_s && p.y>distortion_x-col_s*seed) {\",\n\t\t\t\t\t\"if(seed_x>0.){\",\n\t\t\t\t\t\t\"p.y = 1. - (p.y + distortion_y);\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\t\"else {\",\n\t\t\t\t\t\t\"p.y = distortion_y;\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\"}\",\n\t\t\t\t\"if(p.x<distortion_y+col_s && p.x>distortion_y-col_s*seed) {\",\n\t\t\t\t\t\"if(seed_y>0.){\",\n\t\t\t\t\t\t\"p.x=distortion_x;\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\t\"else {\",\n\t\t\t\t\t\t\"p.x = 1. - (p.x + distortion_x);\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\"}\",\n\t\t\t\t\"p.x+=normal.x*seed_x*(seed/5.);\",\n\t\t\t\t\"p.y+=normal.y*seed_y*(seed/5.);\",\n\t\t\t\t//base from RGB shift shader\n\t\t\t\t\"vec2 offset = amount * vec2( cos(angle), sin(angle));\",\n\t\t\t\t\"vec4 cr = texture2D(tDiffuse, p + offset);\",\n\t\t\t\t\"vec4 cga = texture2D(tDiffuse, p);\",\n\t\t\t\t\"vec4 cb = texture2D(tDiffuse, p - offset);\",\n\t\t\t\t\"gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);\",\n\t\t\t\t//add noise\n\t\t\t\t\"vec4 snow = 200.*amount*vec4(rand(vec2(xs * seed,ys * seed*50.))*0.2);\",\n\t\t\t\t\"gl_FragColor = gl_FragColor+ snow;\",\n\t\t\t\"}\",\n\t\t\t\"else {\",\n\t\t\t\t\"gl_FragColor=texture2D (tDiffuse, vUv);\",\n\t\t\t\"}\",\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/DotScreenShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Dot screen shader\n * based on glfx.js sepia shader\n * https://github.com/evanw/glfx.js\n */\n\nTHREE.DotScreenShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"tSize\":    { type: \"v2\", value: new THREE.Vector2( 256, 256 ) },\n\t\t\"center\":   { type: \"v2\", value: new THREE.Vector2( 0.5, 0.5 ) },\n\t\t\"angle\":    { type: \"f\", value: 1.57 },\n\t\t\"scale\":    { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform vec2 center;\",\n\t\t\"uniform float angle;\",\n\t\t\"uniform float scale;\",\n\t\t\"uniform vec2 tSize;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"float pattern() {\",\n\n\t\t\t\"float s = sin( angle ), c = cos( angle );\",\n\n\t\t\t\"vec2 tex = vUv * tSize - center;\",\n\t\t\t\"vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale;\",\n\n\t\t\t\"return ( sin( point.x ) * sin( point.y ) ) * 4.0;\",\n\n\t\t\"}\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 color = texture2D( tDiffuse, vUv );\",\n\n\t\t\t\"float average = ( color.r + color.g + color.b ) / 3.0;\",\n\n\t\t\t\"gl_FragColor = vec4( vec3( average * 10.0 - 5.0 + pattern() ), color.a );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/EdgeShader.js",
    "content": "/**\n * @author zz85 / https://github.com/zz85 | https://www.lab4games.net/zz85/blog\n *\n * Edge Detection Shader using Frei-Chen filter\n * Based on http://rastergrid.com/blog/2011/01/frei-chen-edge-detector\n *\n * aspect: vec2 of (1/width, 1/height)\n */\n\nTHREE.EdgeShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"aspect\":    { type: \"v2\", value: new THREE.Vector2( 512, 512 ) },\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"uniform vec2 aspect;\",\n\n\t\t\"vec2 texel = vec2(1.0 / aspect.x, 1.0 / aspect.y);\",\n\n\n\t\t\"mat3 G[9];\",\n\n\t\t// hard coded matrix values!!!! as suggested in https://github.com/neilmendoza/ofxPostProcessing/blob/master/src/EdgePass.cpp#L45\n\n\t\t\"const mat3 g0 = mat3( 0.3535533845424652, 0, -0.3535533845424652, 0.5, 0, -0.5, 0.3535533845424652, 0, -0.3535533845424652 );\",\n\t\t\"const mat3 g1 = mat3( 0.3535533845424652, 0.5, 0.3535533845424652, 0, 0, 0, -0.3535533845424652, -0.5, -0.3535533845424652 );\",\n\t\t\"const mat3 g2 = mat3( 0, 0.3535533845424652, -0.5, -0.3535533845424652, 0, 0.3535533845424652, 0.5, -0.3535533845424652, 0 );\",\n\t\t\"const mat3 g3 = mat3( 0.5, -0.3535533845424652, 0, -0.3535533845424652, 0, 0.3535533845424652, 0, 0.3535533845424652, -0.5 );\",\n\t\t\"const mat3 g4 = mat3( 0, -0.5, 0, 0.5, 0, 0.5, 0, -0.5, 0 );\",\n\t\t\"const mat3 g5 = mat3( -0.5, 0, 0.5, 0, 0, 0, 0.5, 0, -0.5 );\",\n\t\t\"const mat3 g6 = mat3( 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.6666666865348816, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204 );\",\n\t\t\"const mat3 g7 = mat3( -0.3333333432674408, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, 0.6666666865348816, 0.1666666716337204, -0.3333333432674408, 0.1666666716337204, -0.3333333432674408 );\",\n\t\t\"const mat3 g8 = mat3( 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408, 0.3333333432674408 );\",\n\n\t\t\"void main(void)\",\n\t\t\"{\",\n\n\t\t\t\"G[0] = g0,\",\n\t\t\t\"G[1] = g1,\",\n\t\t\t\"G[2] = g2,\",\n\t\t\t\"G[3] = g3,\",\n\t\t\t\"G[4] = g4,\",\n\t\t\t\"G[5] = g5,\",\n\t\t\t\"G[6] = g6,\",\n\t\t\t\"G[7] = g7,\",\n\t\t\t\"G[8] = g8;\",\n\n\t\t\t\"mat3 I;\",\n\t\t\t\"float cnv[9];\",\n\t\t\t\"vec3 sample;\",\n\n\t\t\t/* fetch the 3x3 neighbourhood and use the RGB vector's length as intensity value */\n\t\t\t\"for (float i=0.0; i<3.0; i++) {\",\n\t\t\t\t\"for (float j=0.0; j<3.0; j++) {\",\n\t\t\t\t\t\"sample = texture2D(tDiffuse, vUv + texel * vec2(i-1.0,j-1.0) ).rgb;\",\n\t\t\t\t\t\"I[int(i)][int(j)] = length(sample);\",\n\t\t\t\t\"}\",\n\t\t\t\"}\",\n\n\t\t\t/* calculate the convolution values for all the masks */\n\t\t\t\"for (int i=0; i<9; i++) {\",\n\t\t\t\t\"float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]);\",\n\t\t\t\t\"cnv[i] = dp3 * dp3;\",\n\t\t\t\"}\",\n\n\t\t\t\"float M = (cnv[0] + cnv[1]) + (cnv[2] + cnv[3]);\",\n\t\t\t\"float S = (cnv[4] + cnv[5]) + (cnv[6] + cnv[7]) + (cnv[8] + M);\",\n\n\t\t\t\"gl_FragColor = vec4(vec3(sqrt(M/S)), 1.0);\",\n\t\t\"}\",\n\n\t].join( \"\\n\" )\n};\n"
  },
  {
    "path": "example/js/lib/shaders/EdgeShader2.js",
    "content": "/**\n * @author zz85 / https://github.com/zz85 | https://www.lab4games.net/zz85/blog\n *\n * Edge Detection Shader using Sobel filter\n * Based on http://rastergrid.com/blog/2011/01/frei-chen-edge-detector\n *\n * aspect: vec2 of (1/width, 1/height)\n */\n\nTHREE.EdgeShader2 = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"aspect\":    { type: \"v2\", value: new THREE.Vector2( 512, 512 ) },\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"varying vec2 vUv;\",\n\t\t\"uniform vec2 aspect;\",\n\n\n\t\t\"vec2 texel = vec2(1.0 / aspect.x, 1.0 / aspect.y);\",\n\n\t\t\"mat3 G[2];\",\n\n\t\t\"const mat3 g0 = mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 );\",\n\t\t\"const mat3 g1 = mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 );\",\n\n\n\t\t\"void main(void)\",\n\t\t\"{\",\n\t\t\t\"mat3 I;\",\n\t\t\t\"float cnv[2];\",\n\t\t\t\"vec3 sample;\",\n\n\t\t\t\"G[0] = g0;\",\n\t\t\t\"G[1] = g1;\",\n\n\t\t\t/* fetch the 3x3 neighbourhood and use the RGB vector's length as intensity value */\n\t\t\t\"for (float i=0.0; i<3.0; i++)\",\n\t\t\t\"for (float j=0.0; j<3.0; j++) {\",\n\t\t\t\t\"sample = texture2D( tDiffuse, vUv + texel * vec2(i-1.0,j-1.0) ).rgb;\",\n\t\t\t\t\"I[int(i)][int(j)] = length(sample);\",\n\t\t\t\"}\",\n\n\t\t\t/* calculate the convolution values for all the masks */\n\t\t\t\"for (int i=0; i<2; i++) {\",\n\t\t\t\t\"float dp3 = dot(G[i][0], I[0]) + dot(G[i][1], I[1]) + dot(G[i][2], I[2]);\",\n\t\t\t\t\"cnv[i] = dp3 * dp3; \",\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor = vec4(0.5 * sqrt(cnv[0]*cnv[0]+cnv[1]*cnv[1]));\",\n\t\t\"} \",\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/FXAAShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n * @author davidedc / http://www.sketchpatch.net/\n *\n * NVIDIA FXAA by Timothy Lottes\n * http://timothylottes.blogspot.com/2011/06/fxaa3-source-released.html\n * - WebGL port by @supereggbert\n * http://www.glge.org/demos/fxaa/\n */\n\nTHREE.FXAAShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":   { type: \"t\", value: null },\n\t\t\"resolution\": { type: \"v2\", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"void main() {\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform vec2 resolution;\",\n\n\t\t\"#define FXAA_REDUCE_MIN   (1.0/128.0)\",\n\t\t\"#define FXAA_REDUCE_MUL   (1.0/8.0)\",\n\t\t\"#define FXAA_SPAN_MAX     8.0\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec3 rgbNW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, -1.0 ) ) * resolution ).xyz;\",\n\t\t\t\"vec3 rgbNE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, -1.0 ) ) * resolution ).xyz;\",\n\t\t\t\"vec3 rgbSW = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( -1.0, 1.0 ) ) * resolution ).xyz;\",\n\t\t\t\"vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;\",\n\t\t\t\"vec4 rgbaM  = texture2D( tDiffuse,  gl_FragCoord.xy  * resolution );\",\n\t\t\t\"vec3 rgbM  = rgbaM.xyz;\",\n\t\t\t\"vec3 luma = vec3( 0.299, 0.587, 0.114 );\",\n\n\t\t\t\"float lumaNW = dot( rgbNW, luma );\",\n\t\t\t\"float lumaNE = dot( rgbNE, luma );\",\n\t\t\t\"float lumaSW = dot( rgbSW, luma );\",\n\t\t\t\"float lumaSE = dot( rgbSE, luma );\",\n\t\t\t\"float lumaM  = dot( rgbM,  luma );\",\n\t\t\t\"float lumaMin = min( lumaM, min( min( lumaNW, lumaNE ), min( lumaSW, lumaSE ) ) );\",\n\t\t\t\"float lumaMax = max( lumaM, max( max( lumaNW, lumaNE) , max( lumaSW, lumaSE ) ) );\",\n\n\t\t\t\"vec2 dir;\",\n\t\t\t\"dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\",\n\t\t\t\"dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));\",\n\n\t\t\t\"float dirReduce = max( ( lumaNW + lumaNE + lumaSW + lumaSE ) * ( 0.25 * FXAA_REDUCE_MUL ), FXAA_REDUCE_MIN );\",\n\n\t\t\t\"float rcpDirMin = 1.0 / ( min( abs( dir.x ), abs( dir.y ) ) + dirReduce );\",\n\t\t\t\"dir = min( vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),\",\n\t\t\t\t  \"max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\",\n\t\t\t\t\t\t\"dir * rcpDirMin)) * resolution;\",\n\t\t\t\"vec4 rgbA = (1.0/2.0) * (\",\n        \t\"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (1.0/3.0 - 0.5)) +\",\n\t\t\t\"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (2.0/3.0 - 0.5)));\",\n    \t\t\"vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (\",\n\t\t\t\"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (0.0/3.0 - 0.5)) +\",\n      \t\t\"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (3.0/3.0 - 0.5)));\",\n    \t\t\"float lumaB = dot(rgbB, vec4(luma, 0.0));\",\n\n\t\t\t\"if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {\",\n\n\t\t\t\t\"gl_FragColor = rgbA;\",\n\n\t\t\t\"} else {\",\n\t\t\t\t\"gl_FragColor = rgbB;\",\n\n\t\t\t\"}\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/FilmShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Film grain & scanlines shader\n *\n * - ported from HLSL to WebGL / GLSL\n * http://www.truevision3d.com/forums/showcase/staticnoise_colorblackwhite_scanline_shaders-t18698.0.html\n *\n * Screen Space Static Postprocessor\n *\n * Produces an analogue noise overlay similar to a film grain / TV static\n *\n * Original implementation and noise algorithm\n * Pat 'Hawthorne' Shearon\n *\n * Optimized scanlines + noise version with intensity scaling\n * Georg 'Leviathan' Steinrohder\n *\n * This version is provided under a Creative Commons Attribution 3.0 License\n * http://creativecommons.org/licenses/by/3.0/\n */\n\nTHREE.FilmShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":   { type: \"t\", value: null },\n\t\t\"time\":       { type: \"f\", value: 0.0 },\n\t\t\"nIntensity\": { type: \"f\", value: 0.5 },\n\t\t\"sIntensity\": { type: \"f\", value: 0.05 },\n\t\t\"sCount\":     { type: \"f\", value: 4096 },\n\t\t\"grayscale\":  { type: \"i\", value: 1 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"#include <common>\",\n\t\t\n\t\t// control parameter\n\t\t\"uniform float time;\",\n\n\t\t\"uniform bool grayscale;\",\n\n\t\t// noise effect intensity value (0 = no effect, 1 = full effect)\n\t\t\"uniform float nIntensity;\",\n\n\t\t// scanlines effect intensity value (0 = no effect, 1 = full effect)\n\t\t\"uniform float sIntensity;\",\n\n\t\t// scanlines effect count value (0 = no effect, 4096 = full effect)\n\t\t\"uniform float sCount;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t// sample the source\n\t\t\t\"vec4 cTextureScreen = texture2D( tDiffuse, vUv );\",\n\n\t\t\t// make some noise\n\t\t\t\"float dx = rand( vUv + time );\",\n\n\t\t\t// add noise\n\t\t\t\"vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx, 0.0, 1.0 );\",\n\n\t\t\t// get us a sine and cosine\n\t\t\t\"vec2 sc = vec2( sin( vUv.y * sCount ), cos( vUv.y * sCount ) );\",\n\n\t\t\t// add scanlines\n\t\t\t\"cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * sIntensity;\",\n\n\t\t\t// interpolate between source and result by intensity\n\t\t\t\"cResult = cTextureScreen.rgb + clamp( nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );\",\n\n\t\t\t// convert to grayscale if desired\n\t\t\t\"if( grayscale ) {\",\n\n\t\t\t\t\"cResult = vec3( cResult.r * 0.3 + cResult.g * 0.59 + cResult.b * 0.11 );\",\n\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor =  vec4( cResult, cTextureScreen.a );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/FocusShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Focus shader\n * based on PaintEffect postprocess from ro.me\n * http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js\n */\n\nTHREE.FocusShader = {\n\n\tuniforms : {\n\n\t\t\"tDiffuse\":       { type: \"t\", value: null },\n\t\t\"screenWidth\":    { type: \"f\", value: 1024 },\n\t\t\"screenHeight\":   { type: \"f\", value: 1024 },\n\t\t\"sampleDistance\": { type: \"f\", value: 0.94 },\n\t\t\"waveFactor\":     { type: \"f\", value: 0.00125 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float screenWidth;\",\n\t\t\"uniform float screenHeight;\",\n\t\t\"uniform float sampleDistance;\",\n\t\t\"uniform float waveFactor;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 color, org, tmp, add;\",\n\t\t\t\"float sample_dist, f;\",\n\t\t\t\"vec2 vin;\",\n\t\t\t\"vec2 uv = vUv;\",\n\n\t\t\t\"add = color = org = texture2D( tDiffuse, uv );\",\n\n\t\t\t\"vin = ( uv - vec2( 0.5 ) ) * vec2( 1.4 );\",\n\t\t\t\"sample_dist = dot( vin, vin ) * 2.0;\",\n\n\t\t\t\"f = ( waveFactor * 100.0 + sample_dist ) * sampleDistance * 4.0;\",\n\n\t\t\t\"vec2 sampleSize = vec2(  1.0 / screenWidth, 1.0 / screenHeight ) * vec2( f );\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( 0.111964, 0.993712 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( 0.846724, 0.532032 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( 0.943883, -0.330279 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( 0.330279, -0.943883 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( -0.532032, -0.846724 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( -0.993712, -0.111964 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"add += tmp = texture2D( tDiffuse, uv + vec2( -0.707107, 0.707107 ) * sampleSize );\",\n\t\t\t\"if( tmp.b < color.b ) color = tmp;\",\n\n\t\t\t\"color = color * vec4( 2.0 ) - ( add / vec4( 8.0 ) );\",\n\t\t\t\"color = color + ( add / vec4( 8.0 ) - color ) * ( vec4( 1.0 ) - vec4( sample_dist * 0.5 ) );\",\n\n\t\t\t\"gl_FragColor = vec4( color.rgb * color.rgb * vec3( 0.95 ) + color.rgb, 1.0 );\",\n\n\t\t\"}\"\n\n\n\t].join( \"\\n\" )\n};\n"
  },
  {
    "path": "example/js/lib/shaders/FresnelShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Based on Nvidia Cg tutorial\n */\n\nTHREE.FresnelShader = {\n\n\tuniforms: {\n\n\t\t\"mRefractionRatio\": { type: \"f\", value: 1.02 },\n\t\t\"mFresnelBias\": { type: \"f\", value: 0.1 },\n\t\t\"mFresnelPower\": { type: \"f\", value: 2.0 },\n\t\t\"mFresnelScale\": { type: \"f\", value: 1.0 },\n\t\t\"tCube\": { type: \"t\", value: null }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"uniform float mRefractionRatio;\",\n\t\t\"uniform float mFresnelBias;\",\n\t\t\"uniform float mFresnelScale;\",\n\t\t\"uniform float mFresnelPower;\",\n\n\t\t\"varying vec3 vReflect;\",\n\t\t\"varying vec3 vRefract[3];\",\n\t\t\"varying float vReflectionFactor;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\",\n\t\t\t\"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );\",\n\n\t\t\t\"vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );\",\n\n\t\t\t\"vec3 I = worldPosition.xyz - cameraPosition;\",\n\n\t\t\t\"vReflect = reflect( I, worldNormal );\",\n\t\t\t\"vRefract[0] = refract( normalize( I ), worldNormal, mRefractionRatio );\",\n\t\t\t\"vRefract[1] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.99 );\",\n\t\t\t\"vRefract[2] = refract( normalize( I ), worldNormal, mRefractionRatio * 0.98 );\",\n\t\t\t\"vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), mFresnelPower );\",\n\n\t\t\t\"gl_Position = projectionMatrix * mvPosition;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform samplerCube tCube;\",\n\n\t\t\"varying vec3 vReflect;\",\n\t\t\"varying vec3 vRefract[3];\",\n\t\t\"varying float vReflectionFactor;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );\",\n\t\t\t\"vec4 refractedColor = vec4( 1.0 );\",\n\n\t\t\t\"refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;\",\n\t\t\t\"refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;\",\n\t\t\t\"refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;\",\n\n\t\t\t\"gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/GammaCorrectionShader.js",
    "content": "/**\n * @author WestLangley / http://github.com/WestLangley\n *\n * Gamma Correction Shader\n * http://en.wikipedia.org/wiki/gamma_correction\n */\n\nTHREE.GammaCorrectionShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 tex = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) );\",\n\n\t\t\t\"gl_FragColor = LinearToGamma( tex, float( GAMMA_FACTOR ) );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/HorizontalBlurShader.js",
    "content": "/**\n * @author zz85 / http://www.lab4games.net/zz85/blog\n *\n * Two pass Gaussian blur filter (horizontal and vertical blur shaders)\n * - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/\n *   and used in http://www.cake23.de/traveling-wavefronts-lit-up.html\n *\n * - 9 samples per pass\n * - standard deviation 2.7\n * - \"h\" and \"v\" parameters should be set to \"1 / width\" and \"1 / height\"\n */\n\nTHREE.HorizontalBlurShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"h\":        { type: \"f\", value: 1.0 / 512.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float h;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 sum = vec4( 0.0 );\",\n\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * h, vUv.y ) ) * 0.051;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * h, vUv.y ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * h, vUv.y ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * h, vUv.y ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * h, vUv.y ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * h, vUv.y ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * h, vUv.y ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * h, vUv.y ) ) * 0.051;\",\n\n\t\t\t\"gl_FragColor = sum;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/HorizontalTiltShiftShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position\n *\n * - 9 samples per pass\n * - standard deviation 2.7\n * - \"h\" and \"v\" parameters should be set to \"1 / width\" and \"1 / height\"\n * - \"r\" parameter control where \"focused\" horizontal line lies\n */\n\nTHREE.HorizontalTiltShiftShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"h\":        { type: \"f\", value: 1.0 / 512.0 },\n\t\t\"r\":        { type: \"f\", value: 0.35 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float h;\",\n\t\t\"uniform float r;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 sum = vec4( 0.0 );\",\n\n\t\t\t\"float hh = h * abs( r - vUv.y );\",\n\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 4.0 * hh, vUv.y ) ) * 0.051;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 3.0 * hh, vUv.y ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 2.0 * hh, vUv.y ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x - 1.0 * hh, vUv.y ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 1.0 * hh, vUv.y ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 2.0 * hh, vUv.y ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 3.0 * hh, vUv.y ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x + 4.0 * hh, vUv.y ) ) * 0.051;\",\n\n\t\t\t\"gl_FragColor = sum;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/HueSaturationShader.js",
    "content": "/**\n * @author tapio / http://tapio.github.com/\n *\n * Hue and saturation adjustment\n * https://github.com/evanw/glfx.js\n * hue: -1 to 1 (-1 is 180 degrees in the negative direction, 0 is no change, etc.\n * saturation: -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)\n */\n\nTHREE.HueSaturationShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":   { type: \"t\", value: null },\n\t\t\"hue\":        { type: \"f\", value: 0 },\n\t\t\"saturation\": { type: \"f\", value: 0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float hue;\",\n\t\t\"uniform float saturation;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"gl_FragColor = texture2D( tDiffuse, vUv );\",\n\n\t\t\t// hue\n\t\t\t\"float angle = hue * 3.14159265;\",\n\t\t\t\"float s = sin(angle), c = cos(angle);\",\n\t\t\t\"vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;\",\n\t\t\t\"float len = length(gl_FragColor.rgb);\",\n\t\t\t\"gl_FragColor.rgb = vec3(\",\n\t\t\t\t\"dot(gl_FragColor.rgb, weights.xyz),\",\n\t\t\t\t\"dot(gl_FragColor.rgb, weights.zxy),\",\n\t\t\t\t\"dot(gl_FragColor.rgb, weights.yzx)\",\n\t\t\t\");\",\n\n\t\t\t// saturation\n\t\t\t\"float average = (gl_FragColor.r + gl_FragColor.g + gl_FragColor.b) / 3.0;\",\n\t\t\t\"if (saturation > 0.0) {\",\n\t\t\t\t\"gl_FragColor.rgb += (average - gl_FragColor.rgb) * (1.0 - 1.0 / (1.001 - saturation));\",\n\t\t\t\"} else {\",\n\t\t\t\t\"gl_FragColor.rgb += (average - gl_FragColor.rgb) * (-saturation);\",\n\t\t\t\"}\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/KaleidoShader.js",
    "content": "/**\n * @author felixturner / http://airtight.cc/\n *\n * Kaleidoscope Shader\n * Radial reflection around center point\n * Ported from: http://pixelshaders.com/editor/\n * by Toby Schachman / http://tobyschachman.com/\n *\n * sides: number of reflections\n * angle: initial angle in radians\n */\n\nTHREE.KaleidoShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"sides\":    { type: \"f\", value: 6.0 },\n\t\t\"angle\":    { type: \"f\", value: 0.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float sides;\",\n\t\t\"uniform float angle;\",\n\t\t\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 p = vUv - 0.5;\",\n\t\t\t\"float r = length(p);\",\n\t\t\t\"float a = atan(p.y, p.x) + angle;\",\n\t\t\t\"float tau = 2. * 3.1416 ;\",\n\t\t\t\"a = mod(a, tau/sides);\",\n\t\t\t\"a = abs(a - tau/sides/2.) ;\",\n\t\t\t\"p = r * vec2(cos(a), sin(a));\",\n\t\t\t\"vec4 color = texture2D(tDiffuse, p + 0.5);\",\n\t\t\t\"gl_FragColor = color;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/LuminosityShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Luminosity\n * http://en.wikipedia.org/wiki/Luminosity\n */\n\nTHREE.LuminosityShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 texel = texture2D( tDiffuse, vUv );\",\n\n\t\t\t\"vec3 luma = vec3( 0.299, 0.587, 0.114 );\",\n\n\t\t\t\"float v = dot( texel.xyz, luma );\",\n\n\t\t\t\"gl_FragColor = vec4( v, v, v, texel.w );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/MirrorShader.js",
    "content": "/**\n * @author felixturner / http://airtight.cc/\n *\n * Mirror Shader\n * Copies half the input to the other half\n *\n * side: side of input to mirror (0 = left, 1 = right, 2 = top, 3 = bottom)\n */\n\nTHREE.MirrorShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"side\":     { type: \"i\", value: 1 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform int side;\",\n\t\t\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 p = vUv;\",\n\t\t\t\"if (side == 0){\",\n\t\t\t\t\"if (p.x > 0.5) p.x = 1.0 - p.x;\",\n\t\t\t\"}else if (side == 1){\",\n\t\t\t\t\"if (p.x < 0.5) p.x = 1.0 - p.x;\",\n\t\t\t\"}else if (side == 2){\",\n\t\t\t\t\"if (p.y < 0.5) p.y = 1.0 - p.y;\",\n\t\t\t\"}else if (side == 3){\",\n\t\t\t\t\"if (p.y > 0.5) p.y = 1.0 - p.y;\",\n\t\t\t\"} \",\n\t\t\t\"vec4 color = texture2D(tDiffuse, p);\",\n\t\t\t\"gl_FragColor = color;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/NormalMapShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Normal map shader\n * - compute normals from heightmap\n */\n\nTHREE.NormalMapShader = {\n\n\tuniforms: {\n\n\t\t\"heightMap\":  { type: \"t\", value: null },\n\t\t\"resolution\": { type: \"v2\", value: new THREE.Vector2( 512, 512 ) },\n\t\t\"scale\":      { type: \"v2\", value: new THREE.Vector2( 1, 1 ) },\n\t\t\"height\":     { type: \"f\", value: 0.05 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float height;\",\n\t\t\"uniform vec2 resolution;\",\n\t\t\"uniform sampler2D heightMap;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"float val = texture2D( heightMap, vUv ).x;\",\n\n\t\t\t\"float valU = texture2D( heightMap, vUv + vec2( 1.0 / resolution.x, 0.0 ) ).x;\",\n\t\t\t\"float valV = texture2D( heightMap, vUv + vec2( 0.0, 1.0 / resolution.y ) ).x;\",\n\n\t\t\t\"gl_FragColor = vec4( ( 0.5 * normalize( vec3( val - valU, val - valV, height  ) ) + 0.5 ), 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/OceanShaders.js",
    "content": "﻿// Author: Aleksandr Albert\n// Website: www.routter.co.tt\n\n// Description: A deep water ocean shader set\n// based on an implementation of a Tessendorf Waves\n// originally presented by David Li ( www.david.li/waves )\n\n// The general method is to apply shaders to simulation Framebuffers\n// and then sample these framebuffers when rendering the ocean mesh\n\n// The set uses 7 shaders:\n\n// -- Simulation shaders\n// [1] ocean_sim_vertex         -> Vertex shader used to set up a 2x2 simulation plane centered at (0,0)\n// [2] ocean_subtransform       -> Fragment shader used to subtransform the mesh (generates the displacement map)\n// [3] ocean_initial_spectrum   -> Fragment shader used to set intitial wave frequency at a texel coordinate\n// [4] ocean_phase              -> Fragment shader used to set wave phase at a texel coordinate\n// [5] ocean_spectrum           -> Fragment shader used to set current wave frequency at a texel coordinate\n// [6] ocean_normal             -> Fragment shader used to set face normals at a texel coordinate\n\n// -- Rendering Shader\n// [7] ocean_main               -> Vertex and Fragment shader used to create the final render\n\n\nTHREE.ShaderLib[ 'ocean_sim_vertex' ] = {\n\tvarying: {\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tvertexShader: [\n\t\t'varying vec2 vUV;',\n\n\t\t'void main (void) {',\n\t\t\t'vUV = position.xy * 0.5 + 0.5;',\n\t\t\t'gl_Position = vec4(position, 1.0 );',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_subtransform' ] = {\n\tuniforms: {\n\t\t\"u_input\": { type: \"t\", value: null },\n\t\t\"u_transformSize\": { type: \"f\", value: 512.0 },\n\t\t\"u_subtransformSize\": { type: \"f\", value: 250.0 }\n\t},\n\tvarying: {\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tfragmentShader: [\n\t\t//GPU FFT using a Stockham formulation\n\n\t\t'precision highp float;',\n\t\t'#include <common>',\n\n\t\t'uniform sampler2D u_input;',\n\t\t'uniform float u_transformSize;',\n\t\t'uniform float u_subtransformSize;',\n\n\t\t'varying vec2 vUV;',\n\n\t\t'vec2 multiplyComplex (vec2 a, vec2 b) {',\n\t\t\t'return vec2(a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]);',\n\t\t'}',\n\n\t\t'void main (void) {',\n\t\t\t'#ifdef HORIZONTAL',\n\t\t\t'float index = vUV.x * u_transformSize - 0.5;',\n\t\t\t'#else',\n\t\t\t'float index = vUV.y * u_transformSize - 0.5;',\n\t\t\t'#endif',\n\n\t\t\t'float evenIndex = floor(index / u_subtransformSize) * (u_subtransformSize * 0.5) + mod(index, u_subtransformSize * 0.5);',\n\n\t\t\t//transform two complex sequences simultaneously\n\t\t\t'#ifdef HORIZONTAL',\n\t\t\t'vec4 even = texture2D(u_input, vec2(evenIndex + 0.5, gl_FragCoord.y) / u_transformSize).rgba;',\n\t\t\t'vec4 odd = texture2D(u_input, vec2(evenIndex + u_transformSize * 0.5 + 0.5, gl_FragCoord.y) / u_transformSize).rgba;',\n\t\t\t'#else',\n\t\t\t'vec4 even = texture2D(u_input, vec2(gl_FragCoord.x, evenIndex + 0.5) / u_transformSize).rgba;',\n\t\t\t'vec4 odd = texture2D(u_input, vec2(gl_FragCoord.x, evenIndex + u_transformSize * 0.5 + 0.5) / u_transformSize).rgba;',\n\t\t\t'#endif',\n\n\t\t\t'float twiddleArgument = -2.0 * PI * (index / u_subtransformSize);',\n\t\t\t'vec2 twiddle = vec2(cos(twiddleArgument), sin(twiddleArgument));',\n\n\t\t\t'vec2 outputA = even.xy + multiplyComplex(twiddle, odd.xy);',\n\t\t\t'vec2 outputB = even.zw + multiplyComplex(twiddle, odd.zw);',\n\n\t\t\t'gl_FragColor = vec4(outputA, outputB);',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_initial_spectrum' ] = {\n\tuniforms: {\n\t\t\"u_wind\": { type: \"v2\", value: new THREE.Vector2( 10.0, 10.0 ) },\n\t\t\"u_resolution\": { type: \"f\", value: 512.0 },\n\t\t\"u_size\": { type: \"f\", value: 250.0 },\n\t},\n\tfragmentShader: [\n\t\t'precision highp float;',\n\t\t'#include <common>',\n\n\t\t'const float G = 9.81;',\n\t\t'const float KM = 370.0;',\n\t\t'const float CM = 0.23;',\n\n\t\t'uniform vec2 u_wind;',\n\t\t'uniform float u_resolution;',\n\t\t'uniform float u_size;',\n\n\t\t'float omega (float k) {',\n\t\t\t'return sqrt(G * k * (1.0 + pow2(k / KM)));',\n\t\t'}',\n\n\t\t'float tanh (float x) {',\n\t\t\t'return (1.0 - exp(-2.0 * x)) / (1.0 + exp(-2.0 * x));',\n\t\t'}',\n\n\t\t'void main (void) {',\n\t\t\t'vec2 coordinates = gl_FragCoord.xy - 0.5;',\n\n\t\t\t'float n = (coordinates.x < u_resolution * 0.5) ? coordinates.x : coordinates.x - u_resolution;',\n\t\t\t'float m = (coordinates.y < u_resolution * 0.5) ? coordinates.y : coordinates.y - u_resolution;',\n\n\t\t\t'vec2 K = (2.0 * PI * vec2(n, m)) / u_size;',\n\t\t\t'float k = length(K);',\n\n\t\t\t'float l_wind = length(u_wind);',\n\n\t\t\t'float Omega = 0.84;',\n\t\t\t'float kp = G * pow2(Omega / l_wind);',\n\n\t\t\t'float c = omega(k) / k;',\n\t\t\t'float cp = omega(kp) / kp;',\n\n\t\t\t'float Lpm = exp(-1.25 * pow2(kp / k));',\n\t\t\t'float gamma = 1.7;',\n\t\t\t'float sigma = 0.08 * (1.0 + 4.0 * pow(Omega, -3.0));',\n\t\t\t'float Gamma = exp(-pow2(sqrt(k / kp) - 1.0) / 2.0 * pow2(sigma));',\n\t\t\t'float Jp = pow(gamma, Gamma);',\n\t\t\t'float Fp = Lpm * Jp * exp(-Omega / sqrt(10.0) * (sqrt(k / kp) - 1.0));',\n\t\t\t'float alphap = 0.006 * sqrt(Omega);',\n\t\t\t'float Bl = 0.5 * alphap * cp / c * Fp;',\n\n\t\t\t'float z0 = 0.000037 * pow2(l_wind) / G * pow(l_wind / cp, 0.9);',\n\t\t\t'float uStar = 0.41 * l_wind / log(10.0 / z0);',\n\t\t\t'float alpham = 0.01 * ((uStar < CM) ? (1.0 + log(uStar / CM)) : (1.0 + 3.0 * log(uStar / CM)));',\n\t\t\t'float Fm = exp(-0.25 * pow2(k / KM - 1.0));',\n\t\t\t'float Bh = 0.5 * alpham * CM / c * Fm * Lpm;',\n\n\t\t\t'float a0 = log(2.0) / 4.0;',\n\t\t\t'float am = 0.13 * uStar / CM;',\n\t\t\t'float Delta = tanh(a0 + 4.0 * pow(c / cp, 2.5) + am * pow(CM / c, 2.5));',\n\n\t\t\t'float cosPhi = dot(normalize(u_wind), normalize(K));',\n\n\t\t\t'float S = (1.0 / (2.0 * PI)) * pow(k, -4.0) * (Bl + Bh) * (1.0 + Delta * (2.0 * cosPhi * cosPhi - 1.0));',\n\n\t\t\t'float dk = 2.0 * PI / u_size;',\n\t\t\t'float h = sqrt(S / 2.0) * dk;',\n\n\t\t\t'if (K.x == 0.0 && K.y == 0.0) {',\n\t\t\t\t'h = 0.0;', //no DC term\n\t\t\t'}',\n\t\t\t'gl_FragColor = vec4(h, 0.0, 0.0, 0.0);',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_phase' ] = {\n\tuniforms: {\n\t\t\"u_phases\": { type: \"t\", value: null },\n\t\t\"u_deltaTime\": { type: \"f\", value: null },\n\t\t\"u_resolution\": { type: \"f\", value: null },\n\t\t\"u_size\": { type: \"f\", value: null },\n\t},\n\tvarying: {\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tfragmentShader: [\n\t\t'precision highp float;',\n\t\t'#include <common>',\n\n\t\t'const float G = 9.81;',\n\t\t'const float KM = 370.0;',\n\n\t\t'varying vec2 vUV;',\n\n\t\t'uniform sampler2D u_phases;',\n\t\t'uniform float u_deltaTime;',\n\t\t'uniform float u_resolution;',\n\t\t'uniform float u_size;',\n\n\t\t'float omega (float k) {',\n\t\t\t'return sqrt(G * k * (1.0 + k * k / KM * KM));',\n\t\t'}',\n\n\t\t'void main (void) {',\n\t\t\t'float deltaTime = 1.0 / 60.0;',\n\t\t\t'vec2 coordinates = gl_FragCoord.xy - 0.5;',\n\t\t\t'float n = (coordinates.x < u_resolution * 0.5) ? coordinates.x : coordinates.x - u_resolution;',\n\t\t\t'float m = (coordinates.y < u_resolution * 0.5) ? coordinates.y : coordinates.y - u_resolution;',\n\t\t\t'vec2 waveVector = (2.0 * PI * vec2(n, m)) / u_size;',\n\n\t\t\t'float phase = texture2D(u_phases, vUV).r;',\n\t\t\t'float deltaPhase = omega(length(waveVector)) * u_deltaTime;',\n\t\t\t'phase = mod(phase + deltaPhase, 2.0 * PI);',\n\n\t\t\t'gl_FragColor = vec4(phase, 0.0, 0.0, 0.0);',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_spectrum' ] = {\n\tuniforms: {\n\t\t\"u_size\": { type: \"f\", value: null },\n\t\t\"u_resolution\": { type: \"f\", value: null },\n\t\t\"u_choppiness\": { type: \"f\", value: null },\n\t\t\"u_phases\": { type: \"t\", value: null },\n\t\t\"u_initialSpectrum\": { type: \"t\", value: null },\n\t},\n\tvarying: {\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tfragmentShader: [\n\t\t'precision highp float;',\n\t\t'#include <common>',\n\n\t\t'const float G = 9.81;',\n\t\t'const float KM = 370.0;',\n\n\t\t'varying vec2 vUV;',\n\n\t\t'uniform float u_size;',\n\t\t'uniform float u_resolution;',\n\t\t'uniform float u_choppiness;',\n\t\t'uniform sampler2D u_phases;',\n\t\t'uniform sampler2D u_initialSpectrum;',\n\n\t\t'vec2 multiplyComplex (vec2 a, vec2 b) {',\n\t\t\t'return vec2(a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]);',\n\t\t'}',\n\n\t\t'vec2 multiplyByI (vec2 z) {',\n\t\t\t'return vec2(-z[1], z[0]);',\n\t\t'}',\n\n\t\t'float omega (float k) {',\n\t\t\t'return sqrt(G * k * (1.0 + k * k / KM * KM));',\n\t\t'}',\n\n\t\t'void main (void) {',\n\t\t\t'vec2 coordinates = gl_FragCoord.xy - 0.5;',\n\t\t\t'float n = (coordinates.x < u_resolution * 0.5) ? coordinates.x : coordinates.x - u_resolution;',\n\t\t\t'float m = (coordinates.y < u_resolution * 0.5) ? coordinates.y : coordinates.y - u_resolution;',\n\t\t\t'vec2 waveVector = (2.0 * PI * vec2(n, m)) / u_size;',\n\n\t\t\t'float phase = texture2D(u_phases, vUV).r;',\n\t\t\t'vec2 phaseVector = vec2(cos(phase), sin(phase));',\n\n\t\t\t'vec2 h0 = texture2D(u_initialSpectrum, vUV).rg;',\n\t\t\t'vec2 h0Star = texture2D(u_initialSpectrum, vec2(1.0 - vUV + 1.0 / u_resolution)).rg;',\n\t\t\t'h0Star.y *= -1.0;',\n\n\t\t\t'vec2 h = multiplyComplex(h0, phaseVector) + multiplyComplex(h0Star, vec2(phaseVector.x, -phaseVector.y));',\n\n\t\t\t'vec2 hX = -multiplyByI(h * (waveVector.x / length(waveVector))) * u_choppiness;',\n\t\t\t'vec2 hZ = -multiplyByI(h * (waveVector.y / length(waveVector))) * u_choppiness;',\n\n\t\t\t//no DC term\n\t\t\t'if (waveVector.x == 0.0 && waveVector.y == 0.0) {',\n\t\t\t\t'h = vec2(0.0);',\n\t\t\t\t'hX = vec2(0.0);',\n\t\t\t\t'hZ = vec2(0.0);',\n\t\t\t'}',\n\n\t\t\t'gl_FragColor = vec4(hX + multiplyByI(h), hZ);',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_normals' ] = {\n\tuniforms: {\n\t\t\"u_displacementMap\": { type: \"t\", value: null },\n\t\t\"u_resolution\": { type: \"f\", value: null },\n\t\t\"u_size\": { type: \"f\", value: null },\n\t},\n\tvarying: {\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tfragmentShader: [\n\t\t'precision highp float;',\n\n\t\t'varying vec2 vUV;',\n\n\t\t'uniform sampler2D u_displacementMap;',\n\t\t'uniform float u_resolution;',\n\t\t'uniform float u_size;',\n\n\t\t'void main (void) {',\n\t\t\t'float texel = 1.0 / u_resolution;',\n\t\t\t'float texelSize = u_size / u_resolution;',\n\n\t\t\t'vec3 center = texture2D(u_displacementMap, vUV).rgb;',\n\t\t\t'vec3 right = vec3(texelSize, 0.0, 0.0) + texture2D(u_displacementMap, vUV + vec2(texel, 0.0)).rgb - center;',\n\t\t\t'vec3 left = vec3(-texelSize, 0.0, 0.0) + texture2D(u_displacementMap, vUV + vec2(-texel, 0.0)).rgb - center;',\n\t\t\t'vec3 top = vec3(0.0, 0.0, -texelSize) + texture2D(u_displacementMap, vUV + vec2(0.0, -texel)).rgb - center;',\n\t\t\t'vec3 bottom = vec3(0.0, 0.0, texelSize) + texture2D(u_displacementMap, vUV + vec2(0.0, texel)).rgb - center;',\n\n\t\t\t'vec3 topRight = cross(right, top);',\n\t\t\t'vec3 topLeft = cross(top, left);',\n\t\t\t'vec3 bottomLeft = cross(left, bottom);',\n\t\t\t'vec3 bottomRight = cross(bottom, right);',\n\n\t\t\t'gl_FragColor = vec4(normalize(topRight + topLeft + bottomLeft + bottomRight), 1.0);',\n\t\t'}'\n\t].join( '\\n' )\n};\nTHREE.ShaderLib[ 'ocean_main' ] = {\n\tuniforms: {\n\t\t\"u_displacementMap\": { type: \"t\", value: null },\n\t\t\"u_normalMap\": { type: \"t\", value: null },\n\t\t\"u_geometrySize\": { type: \"f\", value: null },\n\t\t\"u_size\": { type: \"f\", value: null },\n\t\t\"u_projectionMatrix\": { type: \"m4\", value: null },\n\t\t\"u_viewMatrix\": { type: \"m4\", value: null },\n\t\t\"u_cameraPosition\": { type: \"v3\", value: null },\n\t\t\"u_skyColor\": { type: \"v3\", value: null },\n\t\t\"u_oceanColor\": { type: \"v3\", value: null },\n\t\t\"u_sunDirection\": { type: \"v3\", value: null },\n\t\t\"u_exposure\": { type: \"f\", value: null },\n\t},\n\tvarying: {\n\t\t\"vPos\": { type: \"v3\" },\n\t\t\"vUV\": { type: \"v2\" }\n\t},\n\tvertexShader: [\n\t\t'precision highp float;',\n\n\t\t'varying vec3 vPos;',\n\t\t'varying vec2 vUV;',\n\n\t\t'uniform mat4 u_projectionMatrix;',\n\t\t'uniform mat4 u_viewMatrix;',\n\t\t'uniform float u_size;',\n\t\t'uniform float u_geometrySize;',\n\t\t'uniform sampler2D u_displacementMap;',\n\n\t\t'void main (void) {',\n\t\t\t'vec3 newPos = position + texture2D(u_displacementMap, uv).rgb * (u_geometrySize / u_size);',\n\t\t\t'vPos = newPos;',\n\t\t\t'vUV = uv;',\n\t\t\t'gl_Position = u_projectionMatrix * u_viewMatrix * vec4(newPos, 1.0);',\n\t\t'}'\n\t].join( '\\n' ),\n\tfragmentShader: [\n\t\t'precision highp float;',\n\n\t\t'varying vec3 vPos;',\n\t\t'varying vec2 vUV;',\n\n\t\t'uniform sampler2D u_displacementMap;',\n\t\t'uniform sampler2D u_normalMap;',\n\t\t'uniform vec3 u_cameraPosition;',\n\t\t'uniform vec3 u_oceanColor;',\n\t\t'uniform vec3 u_skyColor;',\n\t\t'uniform vec3 u_sunDirection;',\n\t\t'uniform float u_exposure;',\n\n\t\t'vec3 hdr (vec3 color, float exposure) {',\n\t\t\t'return 1.0 - exp(-color * exposure);',\n\t\t'}',\n\n\t\t'void main (void) {',\n\t\t\t'vec3 normal = texture2D(u_normalMap, vUV).rgb;',\n\n\t\t\t'vec3 view = normalize(u_cameraPosition - vPos);',\n\t\t\t'float fresnel = 0.02 + 0.98 * pow(1.0 - dot(normal, view), 5.0);',\n\t\t\t'vec3 sky = fresnel * u_skyColor;',\n\n\t\t\t'float diffuse = clamp(dot(normal, normalize(u_sunDirection)), 0.0, 1.0);',\n\t\t\t'vec3 water = (1.0 - fresnel) * u_oceanColor * u_skyColor * diffuse;',\n\n\t\t\t'vec3 color = sky + water;',\n\n\t\t\t'gl_FragColor = vec4(hdr(color, u_exposure), 1.0);',\n\t\t'}'\n\t].join( '\\n' )\n};\n"
  },
  {
    "path": "example/js/lib/shaders/ParallaxShader.js",
    "content": "// Parallax Occlusion shaders from\n//    http://sunandblackcat.com/tipFullView.php?topicid=28\n// No tangent-space transforms logic based on\n//   http://mmikkelsen3d.blogspot.sk/2012/02/parallaxpoc-mapping-and-no-tangent.html\n\nTHREE.ParallaxShader = {\n\t// Ordered from fastest to best quality.\n\tmodes: {\n\t\tnone:  'NO_PARALLAX',\n\t\tbasic: 'USE_BASIC_PARALLAX',\n\t\tsteep: 'USE_STEEP_PARALLAX',\n\t\tocclusion: 'USE_OCLUSION_PARALLAX', // a.k.a. POM\n\t\trelief: 'USE_RELIEF_PARALLAX',\n\t},\n\n\tuniforms: {\n\t\t\"bumpMap\": { type: \"t\", value: null },\n\t\t\"map\": { type: \"t\", value: null },\n\t\t\"parallaxScale\": { type: \"f\", value: null },\n\t\t\"parallaxMinLayers\": { type: \"f\", value: null },\n\t\t\"parallaxMaxLayers\": { type: \"f\", value: null }\n\t},\n\n\tvertexShader: [\n\t\t\"varying vec2 vUv;\",\n\t\t\"varying vec3 vViewPosition;\",\n\t\t\"varying vec3 vNormal;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\",\n\t\t\t\"vViewPosition = -mvPosition.xyz;\",\n\t\t\t\"vNormal = normalize( normalMatrix * normal );\",\n\t\t\t\"gl_Position = projectionMatrix * mvPosition;\",\n\n\t\t\"}\"\n\n  ].join( \"\\n\" ),\n\n\tfragmentShader: [\n\t\t\"uniform sampler2D bumpMap;\",\n\t\t\"uniform sampler2D map;\",\n\n\t\t\"uniform float parallaxScale;\",\n\t\t\"uniform float parallaxMinLayers;\",\n\t\t\"uniform float parallaxMaxLayers;\",\n\n\t\t\"varying vec2 vUv;\",\n\t\t\"varying vec3 vViewPosition;\",\n\t\t\"varying vec3 vNormal;\",\n\n\t\t\"#ifdef USE_BASIC_PARALLAX\",\n\n\t\t\t\"vec2 parallaxMap( in vec3 V ) {\",\n\n\t\t\t\t\"float initialHeight = texture2D( bumpMap, vUv ).r;\",\n\n\t\t\t\t// No Offset Limitting: messy, floating output at grazing angles.\n\t\t\t\t//\"vec2 texCoordOffset = parallaxScale * V.xy / V.z * initialHeight;\",\n\n\t\t\t\t// Offset Limiting\n\t\t\t\t\"vec2 texCoordOffset = parallaxScale * V.xy * initialHeight;\",\n\t\t\t\t\"return vUv - texCoordOffset;\",\n\n\t\t\t\"}\",\n\n\t\t\"#else\",\n\n\t\t\t\"vec2 parallaxMap( in vec3 V ) {\",\n\n\t\t\t\t// Determine number of layers from angle between V and N\n\t\t\t\t\"float numLayers = mix( parallaxMaxLayers, parallaxMinLayers, abs( dot( vec3( 0.0, 0.0, 1.0 ), V ) ) );\",\n\n\t\t\t\t\"float layerHeight = 1.0 / numLayers;\",\n\t\t\t\t\"float currentLayerHeight = 0.0;\",\n\t\t\t\t// Shift of texture coordinates for each iteration\n\t\t\t\t\"vec2 dtex = parallaxScale * V.xy / V.z / numLayers;\",\n\n\t\t\t\t\"vec2 currentTextureCoords = vUv;\",\n\n\t\t\t\t\"float heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;\",\n\n\t\t\t\t// while ( heightFromTexture > currentLayerHeight )\n\t\t\t\t// Infinite loops are not well supported. Do a \"large\" finite\n\t\t\t\t// loop, but not too large, as it slows down some compilers.\n\t\t\t\t\"for ( int i = 0; i < 30; i += 1 ) {\",\n\t\t\t\t\t\"if ( heightFromTexture <= currentLayerHeight ) {\",\n\t\t\t\t\t\t\"break;\",\n\t\t\t\t\t\"}\",\n\t\t\t\t\t\"currentLayerHeight += layerHeight;\",\n\t\t\t\t\t// Shift texture coordinates along vector V\n\t\t\t\t\t\"currentTextureCoords -= dtex;\",\n\t\t\t\t\t\"heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;\",\n\t\t\t\t\"}\",\n\n\t\t\t\t\"#ifdef USE_STEEP_PARALLAX\",\n\n\t\t\t\t\t\"return currentTextureCoords;\",\n\n\t\t\t\t\"#elif defined( USE_RELIEF_PARALLAX )\",\n\n\t\t\t\t\t\"vec2 deltaTexCoord = dtex / 2.0;\",\n\t\t\t\t\t\"float deltaHeight = layerHeight / 2.0;\",\n\n\t\t\t\t\t// Return to the mid point of previous layer\n\t\t\t\t\t\"currentTextureCoords += deltaTexCoord;\",\n\t\t\t\t\t\"currentLayerHeight -= deltaHeight;\",\n\n\t\t\t\t\t// Binary search to increase precision of Steep Parallax Mapping\n\t\t\t\t\t\"const int numSearches = 5;\",\n\t\t\t\t\t\"for ( int i = 0; i < numSearches; i += 1 ) {\",\n\n\t\t\t\t\t\t\"deltaTexCoord /= 2.0;\",\n\t\t\t\t\t\t\"deltaHeight /= 2.0;\",\n\t\t\t\t\t\t\"heightFromTexture = texture2D( bumpMap, currentTextureCoords ).r;\",\n\t\t\t\t\t\t// Shift along or against vector V\n\t\t\t\t\t\t\"if( heightFromTexture > currentLayerHeight ) {\", // Below the surface\n\n\t\t\t\t\t\t\t\"currentTextureCoords -= deltaTexCoord;\",\n\t\t\t\t\t\t\t\"currentLayerHeight += deltaHeight;\",\n\n\t\t\t\t\t\t\"} else {\", // above the surface\n\n\t\t\t\t\t\t\t\"currentTextureCoords += deltaTexCoord;\",\n\t\t\t\t\t\t\t\"currentLayerHeight -= deltaHeight;\",\n\n\t\t\t\t\t\t\"}\",\n\n\t\t\t\t\t\"}\",\n\t\t\t\t\t\"return currentTextureCoords;\",\n\n\t\t\t\t\"#elif defined( USE_OCLUSION_PARALLAX )\",\n\n\t\t\t\t\t\"vec2 prevTCoords = currentTextureCoords + dtex;\",\n\n\t\t\t\t\t// Heights for linear interpolation\n\t\t\t\t\t\"float nextH = heightFromTexture - currentLayerHeight;\",\n\t\t\t\t\t\"float prevH = texture2D( bumpMap, prevTCoords ).r - currentLayerHeight + layerHeight;\",\n\n\t\t\t\t\t// Proportions for linear interpolation\n\t\t\t\t\t\"float weight = nextH / ( nextH - prevH );\",\n\n\t\t\t\t\t// Interpolation of texture coordinates\n\t\t\t\t\t\"return prevTCoords * weight + currentTextureCoords * ( 1.0 - weight );\",\n\n\t\t\t\t\"#else\", // NO_PARALLAX\n\n\t\t\t\t\t\"return vUv;\",\n\n\t\t\t\t\"#endif\",\n\n\t\t\t\"}\",\n\t\t\"#endif\",\n\n\t\t\"vec2 perturbUv( vec3 surfPosition, vec3 surfNormal, vec3 viewPosition ) {\",\n\n \t\t\t\"vec2 texDx = dFdx( vUv );\",\n\t\t\t\"vec2 texDy = dFdy( vUv );\",\n\n\t\t\t\"vec3 vSigmaX = dFdx( surfPosition );\",\n\t\t\t\"vec3 vSigmaY = dFdy( surfPosition );\",\n\t\t\t\"vec3 vR1 = cross( vSigmaY, surfNormal );\",\n\t\t\t\"vec3 vR2 = cross( surfNormal, vSigmaX );\",\n\t\t\t\"float fDet = dot( vSigmaX, vR1 );\",\n\n\t\t\t\"vec2 vProjVscr = ( 1.0 / fDet ) * vec2( dot( vR1, viewPosition ), dot( vR2, viewPosition ) );\",\n\t\t\t\"vec3 vProjVtex;\",\n\t\t\t\"vProjVtex.xy = texDx * vProjVscr.x + texDy * vProjVscr.y;\",\n\t\t\t\"vProjVtex.z = dot( surfNormal, viewPosition );\",\n\n\t\t\t\"return parallaxMap( vProjVtex );\",\n\t\t\"}\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 mapUv = perturbUv( -vViewPosition, normalize( vNormal ), normalize( vViewPosition ) );\",\n\t\t\t\"gl_FragColor = texture2D( map, mapUv );\",\n\n\t\t\"}\",\n\n  ].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/RGBShiftShader.js",
    "content": "/**\n * @author felixturner / http://airtight.cc/\n *\n * RGB Shift Shader\n * Shifts red and blue channels from center in opposite directions\n * Ported from http://kriss.cx/tom/2009/05/rgb-shift/\n * by Tom Butterworth / http://kriss.cx/tom/\n *\n * amount: shift distance (1 is width of input)\n * angle: shift angle in radians\n */\n\nTHREE.RGBShiftShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"amount\":   { type: \"f\", value: 0.005 },\n\t\t\"angle\":    { type: \"f\", value: 0.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float amount;\",\n\t\t\"uniform float angle;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 offset = amount * vec2( cos(angle), sin(angle));\",\n\t\t\t\"vec4 cr = texture2D(tDiffuse, vUv + offset);\",\n\t\t\t\"vec4 cga = texture2D(tDiffuse, vUv);\",\n\t\t\t\"vec4 cb = texture2D(tDiffuse, vUv - offset);\",\n\t\t\t\"gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/SMAAShader.js",
    "content": "/**\r\n * @author mpk / http://polko.me/\r\n *\r\n * WebGL port of Subpixel Morphological Antialiasing (SMAA) v2.8\r\n * Preset: SMAA 1x Medium (with color edge detection)\r\n * https://github.com/iryoku/smaa/releases/tag/v2.8\r\n */\r\n\r\nTHREE.SMAAShader = [ {\r\n\r\n\tdefines: {\r\n\r\n\t\t\"SMAA_THRESHOLD\": \"0.1\"\r\n\r\n\t},\r\n\r\n\tuniforms: {\r\n\r\n\t\t\"tDiffuse\":\t\t{ type: \"t\", value: null },\r\n\t\t\"resolution\":\t{ type: \"v2\", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }\r\n\r\n\t},\r\n\r\n\tvertexShader: [\r\n\r\n\t\t\"uniform vec2 resolution;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[ 3 ];\",\r\n\r\n\t\t\"void SMAAEdgeDetectionVS( vec2 texcoord ) {\",\r\n\t\t\t\"vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0,  1.0 );\", // WebGL port note: Changed sign in W component\r\n\t\t\t\"vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4(  1.0, 0.0, 0.0, -1.0 );\", // WebGL port note: Changed sign in W component\r\n\t\t\t\"vOffset[ 2 ] = texcoord.xyxy + resolution.xyxy * vec4( -2.0, 0.0, 0.0,  2.0 );\", // WebGL port note: Changed sign in W component\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"vUv = uv;\",\r\n\r\n\t\t\t\"SMAAEdgeDetectionVS( vUv );\",\r\n\r\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\"),\r\n\r\n\tfragmentShader: [\r\n\r\n\t\t\"uniform sampler2D tDiffuse;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[ 3 ];\",\r\n\r\n\t\t\"vec4 SMAAColorEdgeDetectionPS( vec2 texcoord, vec4 offset[3], sampler2D colorTex ) {\",\r\n\t\t\t\"vec2 threshold = vec2( SMAA_THRESHOLD, SMAA_THRESHOLD );\",\r\n\r\n\t\t\t// Calculate color deltas:\r\n\t\t\t\"vec4 delta;\",\r\n\t\t\t\"vec3 C = texture2D( colorTex, texcoord ).rgb;\",\r\n\r\n\t\t\t\"vec3 Cleft = texture2D( colorTex, offset[0].xy ).rgb;\",\r\n\t\t\t\"vec3 t = abs( C - Cleft );\",\r\n\t\t\t\"delta.x = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t\"vec3 Ctop = texture2D( colorTex, offset[0].zw ).rgb;\",\r\n\t\t\t\"t = abs( C - Ctop );\",\r\n\t\t\t\"delta.y = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t// We do the usual threshold:\r\n\t\t\t\"vec2 edges = step( threshold, delta.xy );\",\r\n\r\n\t\t\t// Then discard if there is no edge:\r\n\t\t\t\"if ( dot( edges, vec2( 1.0, 1.0 ) ) == 0.0 )\",\r\n\t\t\t\t\"discard;\",\r\n\r\n\t\t\t// Calculate right and bottom deltas:\r\n\t\t\t\"vec3 Cright = texture2D( colorTex, offset[1].xy ).rgb;\",\r\n\t\t\t\"t = abs( C - Cright );\",\r\n\t\t\t\"delta.z = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t\"vec3 Cbottom  = texture2D( colorTex, offset[1].zw ).rgb;\",\r\n\t\t\t\"t = abs( C - Cbottom );\",\r\n\t\t\t\"delta.w = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t// Calculate the maximum delta in the direct neighborhood:\r\n\t\t\t\"float maxDelta = max( max( max( delta.x, delta.y ), delta.z ), delta.w );\",\r\n\r\n\t\t\t// Calculate left-left and top-top deltas:\r\n\t\t\t\"vec3 Cleftleft  = texture2D( colorTex, offset[2].xy ).rgb;\",\r\n\t\t\t\"t = abs( C - Cleftleft );\",\r\n\t\t\t\"delta.z = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t\"vec3 Ctoptop = texture2D( colorTex, offset[2].zw ).rgb;\",\r\n\t\t\t\"t = abs( C - Ctoptop );\",\r\n\t\t\t\"delta.w = max( max( t.r, t.g ), t.b );\",\r\n\r\n\t\t\t// Calculate the final maximum delta:\r\n\t\t\t\"maxDelta = max( max( maxDelta, delta.z ), delta.w );\",\r\n\r\n\t\t\t// Local contrast adaptation in action:\r\n\t\t\t\"edges.xy *= step( 0.5 * maxDelta, delta.xy );\",\r\n\r\n\t\t\t\"return vec4( edges, 0.0, 0.0 );\",\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"gl_FragColor = SMAAColorEdgeDetectionPS( vUv, vOffset, tDiffuse );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\")\r\n\r\n}, {\r\n\r\n\tdefines: {\r\n\r\n\t\t\"SMAA_MAX_SEARCH_STEPS\":\t\t\"8\",\r\n\t\t\"SMAA_AREATEX_MAX_DISTANCE\":\t\"16\",\r\n\t\t\"SMAA_AREATEX_PIXEL_SIZE\":\t\t\"( 1.0 / vec2( 160.0, 560.0 ) )\",\r\n\t\t\"SMAA_AREATEX_SUBTEX_SIZE\":\t\t\"( 1.0 / 7.0 )\"\r\n\r\n\t},\r\n\r\n\tuniforms: {\r\n\r\n\t\t\"tDiffuse\":\t\t{ type: \"t\", value: null },\r\n\t\t\"tArea\":\t\t{ type: \"t\", value: null },\r\n\t\t\"tSearch\":\t\t{ type: \"t\", value: null },\r\n\t\t\"resolution\":\t{ type: \"v2\", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }\r\n\r\n\t},\r\n\r\n\tvertexShader: [\r\n\r\n\t\t\"uniform vec2 resolution;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[ 3 ];\",\r\n\t\t\"varying vec2 vPixcoord;\",\r\n\r\n\t\t\"void SMAABlendingWeightCalculationVS( vec2 texcoord ) {\",\r\n\t\t\t\"vPixcoord = texcoord / resolution;\",\r\n\r\n\t\t\t// We will use these offsets for the searches later on (see @PSEUDO_GATHER4):\r\n\t\t\t\"vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.25, 0.125, 1.25, 0.125 );\", // WebGL port note: Changed sign in Y and W components\r\n\t\t\t\"vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( -0.125, 0.25, -0.125, -1.25 );\", // WebGL port note: Changed sign in Y and W components\r\n\r\n\t\t\t// And these for the searches, they indicate the ends of the loops:\r\n\t\t\t\"vOffset[ 2 ] = vec4( vOffset[ 0 ].xz, vOffset[ 1 ].yw ) + vec4( -2.0, 2.0, -2.0, 2.0 ) * resolution.xxyy * float( SMAA_MAX_SEARCH_STEPS );\",\r\n\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"vUv = uv;\",\r\n\r\n\t\t\t\"SMAABlendingWeightCalculationVS( vUv );\",\r\n\r\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\"),\r\n\r\n\tfragmentShader: [\r\n\r\n\t\t\"#define SMAASampleLevelZeroOffset( tex, coord, offset ) texture2D( tex, coord + float( offset ) * resolution, 0.0 )\",\r\n\r\n\t\t\"uniform sampler2D tDiffuse;\",\r\n\t\t\"uniform sampler2D tArea;\",\r\n\t\t\"uniform sampler2D tSearch;\",\r\n\t\t\"uniform vec2 resolution;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[3];\",\r\n\t\t\"varying vec2 vPixcoord;\",\r\n\r\n\t\t\"vec2 round( vec2 x ) {\",\r\n\t\t\t\"return sign( x ) * floor( abs( x ) + 0.5 );\",\r\n\t\t\"}\",\r\n\r\n\t\t\"float SMAASearchLength( sampler2D searchTex, vec2 e, float bias, float scale ) {\",\r\n\t\t\t// Not required if searchTex accesses are set to point:\r\n\t\t\t// float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);\r\n\t\t\t// e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +\r\n\t\t\t//     e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;\r\n\t\t\t\"e.r = bias + e.r * scale;\",\r\n\t\t\t\"return 255.0 * texture2D( searchTex, e, 0.0 ).r;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"float SMAASearchXLeft( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\",\r\n\t\t\t/**\r\n\t\t\t* @PSEUDO_GATHER4\r\n\t\t\t* This texcoord has been offset by (-0.25, -0.125) in the vertex shader to\r\n\t\t\t* sample between edge, thus fetching four edges in a row.\r\n\t\t\t* Sampling with different offsets in each direction allows to disambiguate\r\n\t\t\t* which edges are active from the four fetched ones.\r\n\t\t\t*/\r\n\t\t\t\"vec2 e = vec2( 0.0, 1.0 );\",\r\n\r\n\t\t\t\"for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {\", // WebGL port note: Changed while to for\r\n\t\t\t\t\"e = texture2D( edgesTex, texcoord, 0.0 ).rg;\",\r\n\t\t\t\t\"texcoord -= vec2( 2.0, 0.0 ) * resolution;\",\r\n\t\t\t\t\"if ( ! ( texcoord.x > end && e.g > 0.8281 && e.r == 0.0 ) ) break;\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t// We correct the previous (-0.25, -0.125) offset we applied:\r\n\t\t\t\"texcoord.x += 0.25 * resolution.x;\",\r\n\r\n\t\t\t// The searches are bias by 1, so adjust the coords accordingly:\r\n\t\t\t\"texcoord.x += resolution.x;\",\r\n\r\n\t\t\t// Disambiguate the length added by the last step:\r\n\t\t\t\"texcoord.x += 2.0 * resolution.x;\", // Undo last step\r\n\t\t\t\"texcoord.x -= resolution.x * SMAASearchLength(searchTex, e, 0.0, 0.5);\",\r\n\r\n\t\t\t\"return texcoord.x;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"float SMAASearchXRight( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\",\r\n\t\t\t\"vec2 e = vec2( 0.0, 1.0 );\",\r\n\r\n\t\t\t\"for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {\", // WebGL port note: Changed while to for\r\n\t\t\t\t\"e = texture2D( edgesTex, texcoord, 0.0 ).rg;\",\r\n\t\t\t\t\"texcoord += vec2( 2.0, 0.0 ) * resolution;\",\r\n\t\t\t\t\"if ( ! ( texcoord.x < end && e.g > 0.8281 && e.r == 0.0 ) ) break;\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t\"texcoord.x -= 0.25 * resolution.x;\",\r\n\t\t\t\"texcoord.x -= resolution.x;\",\r\n\t\t\t\"texcoord.x -= 2.0 * resolution.x;\",\r\n\t\t\t\"texcoord.x += resolution.x * SMAASearchLength( searchTex, e, 0.5, 0.5 );\",\r\n\r\n\t\t\t\"return texcoord.x;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"float SMAASearchYUp( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\",\r\n\t\t\t\"vec2 e = vec2( 1.0, 0.0 );\",\r\n\r\n\t\t\t\"for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {\", // WebGL port note: Changed while to for\r\n\t\t\t\t\"e = texture2D( edgesTex, texcoord, 0.0 ).rg;\",\r\n\t\t\t\t\"texcoord += vec2( 0.0, 2.0 ) * resolution;\", // WebGL port note: Changed sign\r\n\t\t\t\t\"if ( ! ( texcoord.y > end && e.r > 0.8281 && e.g == 0.0 ) ) break;\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t\"texcoord.y -= 0.25 * resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y -= resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y -= 2.0 * resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y += resolution.y * SMAASearchLength( searchTex, e.gr, 0.0, 0.5 );\", // WebGL port note: Changed sign\r\n\r\n\t\t\t\"return texcoord.y;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"float SMAASearchYDown( sampler2D edgesTex, sampler2D searchTex, vec2 texcoord, float end ) {\",\r\n\t\t\t\"vec2 e = vec2( 1.0, 0.0 );\",\r\n\r\n\t\t\t\"for ( int i = 0; i < SMAA_MAX_SEARCH_STEPS; i ++ ) {\", // WebGL port note: Changed while to for\r\n\t\t\t\t\"e = texture2D( edgesTex, texcoord, 0.0 ).rg;\",\r\n\t\t\t\t\"texcoord -= vec2( 0.0, 2.0 ) * resolution;\", // WebGL port note: Changed sign\r\n\t\t\t\t\"if ( ! ( texcoord.y < end && e.r > 0.8281 && e.g == 0.0 ) ) break;\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t\"texcoord.y += 0.25 * resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y += resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y += 2.0 * resolution.y;\", // WebGL port note: Changed sign\r\n\t\t\t\"texcoord.y -= resolution.y * SMAASearchLength( searchTex, e.gr, 0.5, 0.5 );\", // WebGL port note: Changed sign\r\n\r\n\t\t\t\"return texcoord.y;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"vec2 SMAAArea( sampler2D areaTex, vec2 dist, float e1, float e2, float offset ) {\",\r\n\t\t\t// Rounding prevents precision errors of bilinear filtering:\r\n\t\t\t\"vec2 texcoord = float( SMAA_AREATEX_MAX_DISTANCE ) * round( 4.0 * vec2( e1, e2 ) ) + dist;\",\r\n\r\n\t\t\t// We do a scale and bias for mapping to texel space:\r\n\t\t\t\"texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + ( 0.5 * SMAA_AREATEX_PIXEL_SIZE );\",\r\n\r\n\t\t\t// Move to proper place, according to the subpixel offset:\r\n\t\t\t\"texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;\",\r\n\r\n\t\t\t\"return texture2D( areaTex, texcoord, 0.0 ).rg;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"vec4 SMAABlendingWeightCalculationPS( vec2 texcoord, vec2 pixcoord, vec4 offset[ 3 ], sampler2D edgesTex, sampler2D areaTex, sampler2D searchTex, ivec4 subsampleIndices ) {\",\r\n\t\t\t\"vec4 weights = vec4( 0.0, 0.0, 0.0, 0.0 );\",\r\n\r\n\t\t\t\"vec2 e = texture2D( edgesTex, texcoord ).rg;\",\r\n\r\n\t\t\t\"if ( e.g > 0.0 ) {\", // Edge at north\r\n\t\t\t\t\"vec2 d;\",\r\n\r\n\t\t\t\t// Find the distance to the left:\r\n\t\t\t\t\"vec2 coords;\",\r\n\t\t\t\t\"coords.x = SMAASearchXLeft( edgesTex, searchTex, offset[ 0 ].xy, offset[ 2 ].x );\",\r\n\t\t\t\t\"coords.y = offset[ 1 ].y;\", // offset[1].y = texcoord.y - 0.25 * resolution.y (@CROSSING_OFFSET)\r\n\t\t\t\t\"d.x = coords.x;\",\r\n\r\n\t\t\t\t// Now fetch the left crossing edges, two at a time using bilinear\r\n\t\t\t\t// filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to\r\n\t\t\t\t// discern what value each edge has:\r\n\t\t\t\t\"float e1 = texture2D( edgesTex, coords, 0.0 ).r;\",\r\n\r\n\t\t\t\t// Find the distance to the right:\r\n\t\t\t\t\"coords.x = SMAASearchXRight( edgesTex, searchTex, offset[ 0 ].zw, offset[ 2 ].y );\",\r\n\t\t\t\t\"d.y = coords.x;\",\r\n\r\n\t\t\t\t// We want the distances to be in pixel units (doing this here allow to\r\n\t\t\t\t// better interleave arithmetic and memory accesses):\r\n\t\t\t\t\"d = d / resolution.x - pixcoord.x;\",\r\n\r\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\r\n\t\t\t\t// quadratically:\r\n\t\t\t\t\"vec2 sqrt_d = sqrt( abs( d ) );\",\r\n\r\n\t\t\t\t// Fetch the right crossing edges:\r\n\t\t\t\t\"coords.y -= 1.0 * resolution.y;\", // WebGL port note: Added\r\n\t\t\t\t\"float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 1, 0 ) ).r;\",\r\n\r\n\t\t\t\t// Ok, we know how this pattern looks like, now it is time for getting\r\n\t\t\t\t// the actual area:\r\n\t\t\t\t\"weights.rg = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.y ) );\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t\"if ( e.r > 0.0 ) {\", // Edge at west\r\n\t\t\t\t\"vec2 d;\",\r\n\r\n\t\t\t\t// Find the distance to the top:\r\n\t\t\t\t\"vec2 coords;\",\r\n\r\n\t\t\t\t\"coords.y = SMAASearchYUp( edgesTex, searchTex, offset[ 1 ].xy, offset[ 2 ].z );\",\r\n\t\t\t\t\"coords.x = offset[ 0 ].x;\", // offset[1].x = texcoord.x - 0.25 * resolution.x;\r\n\t\t\t\t\"d.x = coords.y;\",\r\n\r\n\t\t\t\t// Fetch the top crossing edges:\r\n\t\t\t\t\"float e1 = texture2D( edgesTex, coords, 0.0 ).g;\",\r\n\r\n\t\t\t\t// Find the distance to the bottom:\r\n\t\t\t\t\"coords.y = SMAASearchYDown( edgesTex, searchTex, offset[ 1 ].zw, offset[ 2 ].w );\",\r\n\t\t\t\t\"d.y = coords.y;\",\r\n\r\n\t\t\t\t// We want the distances to be in pixel units:\r\n\t\t\t\t\"d = d / resolution.y - pixcoord.y;\",\r\n\r\n\t\t\t\t// SMAAArea below needs a sqrt, as the areas texture is compressed\r\n\t\t\t\t// quadratically:\r\n\t\t\t\t\"vec2 sqrt_d = sqrt( abs( d ) );\",\r\n\r\n\t\t\t\t// Fetch the bottom crossing edges:\r\n\t\t\t\t\"coords.y -= 1.0 * resolution.y;\", // WebGL port note: Added\r\n\t\t\t\t\"float e2 = SMAASampleLevelZeroOffset( edgesTex, coords, ivec2( 0, 1 ) ).g;\",\r\n\r\n\t\t\t\t// Get the area for this direction:\r\n\t\t\t\t\"weights.ba = SMAAArea( areaTex, sqrt_d, e1, e2, float( subsampleIndices.x ) );\",\r\n\t\t\t\"}\",\r\n\r\n\t\t\t\"return weights;\",\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"gl_FragColor = SMAABlendingWeightCalculationPS( vUv, vPixcoord, vOffset, tDiffuse, tArea, tSearch, ivec4( 0.0 ) );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\")\r\n\r\n}, {\r\n\r\n\tuniforms: {\r\n\r\n\t\t\"tDiffuse\":\t\t{ type: \"t\", value: null },\r\n\t\t\"tColor\":\t\t{ type: \"t\", value: null },\r\n\t\t\"resolution\":\t{ type: \"v2\", value: new THREE.Vector2( 1 / 1024, 1 / 512 ) }\r\n\r\n\t},\r\n\r\n\tvertexShader: [\r\n\r\n\t\t\"uniform vec2 resolution;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[ 2 ];\",\r\n\r\n\t\t\"void SMAANeighborhoodBlendingVS( vec2 texcoord ) {\",\r\n\t\t\t\"vOffset[ 0 ] = texcoord.xyxy + resolution.xyxy * vec4( -1.0, 0.0, 0.0, 1.0 );\", // WebGL port note: Changed sign in W component\r\n\t\t\t\"vOffset[ 1 ] = texcoord.xyxy + resolution.xyxy * vec4( 1.0, 0.0, 0.0, -1.0 );\", // WebGL port note: Changed sign in W component\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"vUv = uv;\",\r\n\r\n\t\t\t\"SMAANeighborhoodBlendingVS( vUv );\",\r\n\r\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\"),\r\n\r\n\tfragmentShader: [\r\n\r\n\t\t\"uniform sampler2D tDiffuse;\",\r\n\t\t\"uniform sampler2D tColor;\",\r\n\t\t\"uniform vec2 resolution;\",\r\n\r\n\t\t\"varying vec2 vUv;\",\r\n\t\t\"varying vec4 vOffset[ 2 ];\",\r\n\r\n\t\t\"vec4 SMAANeighborhoodBlendingPS( vec2 texcoord, vec4 offset[ 2 ], sampler2D colorTex, sampler2D blendTex ) {\",\r\n\t\t\t// Fetch the blending weights for current pixel:\r\n\t\t\t\"vec4 a;\",\r\n\t\t\t\"a.xz = texture2D( blendTex, texcoord ).xz;\",\r\n\t\t\t\"a.y = texture2D( blendTex, offset[ 1 ].zw ).g;\",\r\n\t\t\t\"a.w = texture2D( blendTex, offset[ 1 ].xy ).a;\",\r\n\r\n\t\t\t// Is there any blending weight with a value greater than 0.0?\r\n\t\t\t\"if ( dot(a, vec4( 1.0, 1.0, 1.0, 1.0 )) < 1e-5 ) {\",\r\n\t\t\t\t\"return texture2D( colorTex, texcoord, 0.0 );\",\r\n\t\t\t\"} else {\",\r\n\t\t\t\t// Up to 4 lines can be crossing a pixel (one through each edge). We\r\n\t\t\t\t// favor blending by choosing the line with the maximum weight for each\r\n\t\t\t\t// direction:\r\n\t\t\t\t\"vec2 offset;\",\r\n\t\t\t\t\"offset.x = a.a > a.b ? a.a : -a.b;\", // left vs. right\r\n\t\t\t\t\"offset.y = a.g > a.r ? -a.g : a.r;\", // top vs. bottom // WebGL port note: Changed signs\r\n\r\n\t\t\t\t// Then we go in the direction that has the maximum weight:\r\n\t\t\t\t\"if ( abs( offset.x ) > abs( offset.y )) {\", // horizontal vs. vertical\r\n\t\t\t\t\t\"offset.y = 0.0;\",\r\n\t\t\t\t\"} else {\",\r\n\t\t\t\t\t\"offset.x = 0.0;\",\r\n\t\t\t\t\"}\",\r\n\r\n\t\t\t\t// Fetch the opposite color and lerp by hand:\r\n\t\t\t\t\"vec4 C = texture2D( colorTex, texcoord, 0.0 );\",\r\n\t\t\t\t\"texcoord += sign( offset ) * resolution;\",\r\n\t\t\t\t\"vec4 Cop = texture2D( colorTex, texcoord, 0.0 );\",\r\n\t\t\t\t\"float s = abs( offset.x ) > abs( offset.y ) ? abs( offset.x ) : abs( offset.y );\",\r\n\r\n\t\t\t\t// WebGL port note: Added gamma correction\r\n\t\t\t\t\"C.xyz = pow(C.xyz, vec3(2.2));\",\r\n\t\t\t\t\"Cop.xyz = pow(Cop.xyz, vec3(2.2));\",\r\n\t\t\t\t\"vec4 mixed = mix(C, Cop, s);\",\r\n\t\t\t\t\"mixed.xyz = pow(mixed.xyz, vec3(1.0 / 2.2));\",\r\n\r\n\t\t\t\t\"return mixed;\",\r\n\t\t\t\"}\",\r\n\t\t\"}\",\r\n\r\n\t\t\"void main() {\",\r\n\r\n\t\t\t\"gl_FragColor = SMAANeighborhoodBlendingPS( vUv, vOffset, tColor, tDiffuse );\",\r\n\r\n\t\t\"}\"\r\n\r\n\t].join(\"\\n\")\r\n\r\n} ];\r\n"
  },
  {
    "path": "example/js/lib/shaders/SSAOShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Screen-space ambient occlusion shader\n * - ported from\n *   SSAO GLSL shader v1.2\n *   assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com)\n *   original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/)\n * - modifications\n * - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass)\n * - refactoring and optimizations\n */\n\nTHREE.SSAOShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\":     { type: \"t\", value: null },\n\t\t\"tDepth\":       { type: \"t\", value: null },\n\t\t\"size\":         { type: \"v2\", value: new THREE.Vector2( 512, 512 ) },\n\t\t\"cameraNear\":   { type: \"f\", value: 1 },\n\t\t\"cameraFar\":    { type: \"f\", value: 100 },\n\t\t\"onlyAO\":       { type: \"i\", value: 0 },\n\t\t\"aoClamp\":      { type: \"f\", value: 0.5 },\n\t\t\"lumInfluence\": { type: \"f\", value: 0.5 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float cameraNear;\",\n\t\t\"uniform float cameraFar;\",\n\n\t\t\"uniform bool onlyAO;\",      // use only ambient occlusion pass?\n\n\t\t\"uniform vec2 size;\",        // texture width, height\n\t\t\"uniform float aoClamp;\",    // depth clamp - reduces haloing at screen edges\n\n\t\t\"uniform float lumInfluence;\",  // how much luminance affects occlusion\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform sampler2D tDepth;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t// \"#define PI 3.14159265\",\n\t\t\"#define DL 2.399963229728653\",  // PI * ( 3.0 - sqrt( 5.0 ) )\n\t\t\"#define EULER 2.718281828459045\",\n\n\t\t// user variables\n\n\t\t\"const int samples = 8;\",     // ao sample count\n\t\t\"const float radius = 5.0;\",  // ao radius\n\n\t\t\"const bool useNoise = false;\",      // use noise instead of pattern for sample dithering\n\t\t\"const float noiseAmount = 0.0003;\", // dithering amount\n\n\t\t\"const float diffArea = 0.4;\",   // self-shadowing reduction\n\t\t\"const float gDisplace = 0.4;\",  // gauss bell center\n\n\n\t\t// RGBA depth\n\n\t\t\"#include <packing>\",\n\n\t\t// generating noise / pattern texture for dithering\n\n\t\t\"vec2 rand( const vec2 coord ) {\",\n\n\t\t\t\"vec2 noise;\",\n\n\t\t\t\"if ( useNoise ) {\",\n\n\t\t\t\t\"float nx = dot ( coord, vec2( 12.9898, 78.233 ) );\",\n\t\t\t\t\"float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );\",\n\n\t\t\t\t\"noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );\",\n\n\t\t\t\"} else {\",\n\n\t\t\t\t\"float ff = fract( 1.0 - coord.s * ( size.x / 2.0 ) );\",\n\t\t\t\t\"float gg = fract( coord.t * ( size.y / 2.0 ) );\",\n\n\t\t\t\t\"noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"return ( noise * 2.0  - 1.0 ) * noiseAmount;\",\n\n\t\t\"}\",\n\n\t\t\"float readDepth( const in vec2 coord ) {\",\n\n\t\t\t\"float cameraFarPlusNear = cameraFar + cameraNear;\",\n\t\t\t\"float cameraFarMinusNear = cameraFar - cameraNear;\",\n\t\t\t\"float cameraCoef = 2.0 * cameraNear;\",\n\n\t\t\t// \"return ( 2.0 * cameraNear ) / ( cameraFar + cameraNear - unpackDepth( texture2D( tDepth, coord ) ) * ( cameraFar - cameraNear ) );\",\n\t\t\t\"return cameraCoef / ( cameraFarPlusNear - unpackRGBAToDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );\",\n\n\n\t\t\"}\",\n\n\t\t\"float compareDepths( const in float depth1, const in float depth2, inout int far ) {\",\n\n\t\t\t\"float garea = 2.0;\",                         // gauss bell width\n\t\t\t\"float diff = ( depth1 - depth2 ) * 100.0;\",  // depth difference (0-100)\n\n\t\t\t// reduce left bell width to avoid self-shadowing\n\n\t\t\t\"if ( diff < gDisplace ) {\",\n\n\t\t\t\t\"garea = diffArea;\",\n\n\t\t\t\"} else {\",\n\n\t\t\t\t\"far = 1;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"float dd = diff - gDisplace;\",\n\t\t\t\"float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );\",\n\t\t\t\"return gauss;\",\n\n\t\t\"}\",\n\n\t\t\"float calcAO( float depth, float dw, float dh ) {\",\n\n\t\t\t\"float dd = radius - depth * radius;\",\n\t\t\t\"vec2 vv = vec2( dw, dh );\",\n\n\t\t\t\"vec2 coord1 = vUv + dd * vv;\",\n\t\t\t\"vec2 coord2 = vUv - dd * vv;\",\n\n\t\t\t\"float temp1 = 0.0;\",\n\t\t\t\"float temp2 = 0.0;\",\n\n\t\t\t\"int far = 0;\",\n\t\t\t\"temp1 = compareDepths( depth, readDepth( coord1 ), far );\",\n\n\t\t\t// DEPTH EXTRAPOLATION\n\n\t\t\t\"if ( far > 0 ) {\",\n\n\t\t\t\t\"temp2 = compareDepths( readDepth( coord2 ), depth, far );\",\n\t\t\t\t\"temp1 += ( 1.0 - temp1 ) * temp2;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"return temp1;\",\n\n\t\t\"}\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec2 noise = rand( vUv );\",\n\t\t\t\"float depth = readDepth( vUv );\",\n\n\t\t\t\"float tt = clamp( depth, aoClamp, 1.0 );\",\n\n\t\t\t\"float w = ( 1.0 / size.x )  / tt + ( noise.x * ( 1.0 - noise.x ) );\",\n\t\t\t\"float h = ( 1.0 / size.y ) / tt + ( noise.y * ( 1.0 - noise.y ) );\",\n\n\t\t\t\"float ao = 0.0;\",\n\n\t\t\t\"float dz = 1.0 / float( samples );\",\n\t\t\t\"float z = 1.0 - dz / 2.0;\",\n\t\t\t\"float l = 0.0;\",\n\n\t\t\t\"for ( int i = 0; i <= samples; i ++ ) {\",\n\n\t\t\t\t\"float r = sqrt( 1.0 - z );\",\n\n\t\t\t\t\"float pw = cos( l ) * r;\",\n\t\t\t\t\"float ph = sin( l ) * r;\",\n\t\t\t\t\"ao += calcAO( depth, pw * w, ph * h );\",\n\t\t\t\t\"z = z - dz;\",\n\t\t\t\t\"l = l + DL;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"ao /= float( samples );\",\n\t\t\t\"ao = 1.0 - ao;\",\n\n\t\t\t\"vec3 color = texture2D( tDiffuse, vUv ).rgb;\",\n\n\t\t\t\"vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );\",\n\t\t\t\"float lum = dot( color.rgb, lumcoeff );\",\n\t\t\t\"vec3 luminance = vec3( lum );\",\n\n\t\t\t\"vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );\",  // mix( color * ao, white, luminance )\n\n\t\t\t\"if ( onlyAO ) {\",\n\n\t\t\t\t\"final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );\",  // ambient occlusion only\n\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor = vec4( final, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/SelfShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Color correction\n */\n\nTHREE.SelfShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"powRGB\":   { type: \"v3\", value: new THREE.Vector3( 2, 2, 2 ) },\n\t\t\"mulRGB\":   { type: \"v3\", value: new THREE.Vector3( 1, 1, 1 ) },\n\t\t\"addRGB\":   { type: \"v3\", value: new THREE.Vector3( 0, 0, 0 ) }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform vec3 powRGB;\",\n\t\t\"uniform vec3 mulRGB;\",\n\t\t\"uniform vec3 addRGB;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\t\t\t\"gl_FragColor = texture2D( tDiffuse, vUv );\",\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/SepiaShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Sepia tone shader\n * based on glfx.js sepia shader\n * https://github.com/evanw/glfx.js\n */\n\nTHREE.SepiaShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"amount\":   { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float amount;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 color = texture2D( tDiffuse, vUv );\",\n\t\t\t\"vec3 c = color.rgb;\",\n\n\t\t\t\"color.r = dot( c, vec3( 1.0 - 0.607 * amount, 0.769 * amount, 0.189 * amount ) );\",\n\t\t\t\"color.g = dot( c, vec3( 0.349 * amount, 1.0 - 0.314 * amount, 0.168 * amount ) );\",\n\t\t\t\"color.b = dot( c, vec3( 0.272 * amount, 0.534 * amount, 1.0 - 0.869 * amount ) );\",\n\n\t\t\t\"gl_FragColor = vec4( min( vec3( 1.0 ), color.rgb ), color.a );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/TechnicolorShader.js",
    "content": "/**\n * @author flimshaw / http://charliehoey.com\n *\n * Technicolor Shader\n * Simulates the look of the two-strip technicolor process popular in early 20th century films.\n * More historical info here: http://www.widescreenmuseum.com/oldcolor/technicolor1.htm\n * Demo here: http://charliehoey.com/technicolor_shader/shader_test.html\n */\n\nTHREE.TechnicolorShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 tex = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) );\",\n\t\t\t\"vec4 newTex = vec4(tex.r, (tex.g + tex.b) * .5, (tex.g + tex.b) * .5, 1.0);\",\n\n\t\t\t\"gl_FragColor = newTex;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/ToneMapShader.js",
    "content": "/**\n * @author miibond\n *\n * Full-screen tone-mapping shader based on http://www.graphics.cornell.edu/~jaf/publications/sig02_paper.pdf\n */\n\nTHREE.ToneMapShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"averageLuminance\":  { type: \"f\", value: 1.0 },\n\t\t\"luminanceMap\":  { type: \"t\", value: null },\n\t\t\"maxLuminance\":  { type: \"f\", value: 16.0 },\n\t\t\"middleGrey\":  { type: \"f\", value: 0.6 }\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"uniform float middleGrey;\",\n\t\t\"uniform float maxLuminance;\",\n\t\t\"#ifdef ADAPTED_LUMINANCE\",\n\t\t\t\"uniform sampler2D luminanceMap;\",\n\t\t\"#else\",\n\t\t\t\"uniform float averageLuminance;\",\n\t\t\"#endif\",\n\t\t\n\t\t\"const vec3 LUM_CONVERT = vec3(0.299, 0.587, 0.114);\",\n\n\t\t\"vec3 ToneMap( vec3 vColor ) {\",\n\t\t\t\"#ifdef ADAPTED_LUMINANCE\",\n\t\t\t\t// Get the calculated average luminance \n\t\t\t\t\"float fLumAvg = texture2D(luminanceMap, vec2(0.5, 0.5)).r;\",\n\t\t\t\"#else\",\n\t\t\t\t\"float fLumAvg = averageLuminance;\",\n\t\t\t\"#endif\",\n\t\t\t\n\t\t\t// Calculate the luminance of the current pixel\n\t\t\t\"float fLumPixel = dot(vColor, LUM_CONVERT);\",\n\n\t\t\t// Apply the modified operator (Eq. 4)\n\t\t\t\"float fLumScaled = (fLumPixel * middleGrey) / fLumAvg;\",\n\n\t\t\t\"float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (maxLuminance * maxLuminance)))) / (1.0 + fLumScaled);\",\n\t\t\t\"return fLumCompressed * vColor;\",\n\t\t\"}\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 texel = texture2D( tDiffuse, vUv );\",\n\t\t\t\n\t\t\t\"gl_FragColor = vec4( ToneMap( texel.xyz ), texel.w );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/TriangleBlurShader.js",
    "content": "/**\n * @author zz85 / http://www.lab4games.net/zz85/blog\n *\n * Triangle blur shader\n * based on glfx.js triangle blur shader\n * https://github.com/evanw/glfx.js\n *\n * A basic blur filter, which convolves the image with a\n * pyramid filter. The pyramid filter is separable and is applied as two\n * perpendicular triangle filters.\n */\n\nTHREE.TriangleBlurShader = {\n\n\tuniforms : {\n\n\t\t\"texture\": { type: \"t\", value: null },\n\t\t\"delta\":   { type: \"v2\", value: new THREE.Vector2( 1, 1 ) }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"#include <common>\",\n\n\t\t\"#define ITERATIONS 10.0\",\n\n\t\t\"uniform sampler2D texture;\",\n\t\t\"uniform vec2 delta;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 color = vec4( 0.0 );\",\n\n\t\t\t\"float total = 0.0;\",\n\n\t\t\t// randomize the lookup values to hide the fixed number of samples\n\n\t\t\t\"float offset = rand( vUv );\",\n\n\t\t\t\"for ( float t = -ITERATIONS; t <= ITERATIONS; t ++ ) {\",\n\n\t\t\t\t\"float percent = ( t + offset - 0.5 ) / ITERATIONS;\",\n\t\t\t\t\"float weight = 1.0 - abs( percent );\",\n\n\t\t\t\t\"color += texture2D( texture, vUv + delta * percent ) * weight;\",\n\t\t\t\t\"total += weight;\",\n\n\t\t\t\"}\",\n\n\t\t\t\"gl_FragColor = color / total;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/UnpackDepthRGBAShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Unpack RGBA depth shader\n * - show RGBA encoded depth as monochrome color\n */\n\nTHREE.UnpackDepthRGBAShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"opacity\":  { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float opacity;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"#include <packing>\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"float depth = 1.0 - unpackRGBAToDepth( texture2D( tDiffuse, vUv ) );\",\n\t\t\t\"gl_FragColor = opacity * vec4( vec3( depth ), 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/VerticalBlurShader.js",
    "content": "/**\n * @author zz85 / http://www.lab4games.net/zz85/blog\n *\n * Two pass Gaussian blur filter (horizontal and vertical blur shaders)\n * - described in http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/\n *   and used in http://www.cake23.de/traveling-wavefronts-lit-up.html\n *\n * - 9 samples per pass\n * - standard deviation 2.7\n * - \"h\" and \"v\" parameters should be set to \"1 / width\" and \"1 / height\"\n */\n\nTHREE.VerticalBlurShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"v\":        { type: \"f\", value: 1.0 / 512.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float v;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 sum = vec4( 0.0 );\",\n\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * v ) ) * 0.051;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * v ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * v ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * v ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * v ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * v ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * v ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * v ) ) * 0.051;\",\n\n\t\t\t\"gl_FragColor = sum;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/VerticalTiltShiftShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Simple fake tilt-shift effect, modulating two pass Gaussian blur (see above) by vertical position\n *\n * - 9 samples per pass\n * - standard deviation 2.7\n * - \"h\" and \"v\" parameters should be set to \"1 / width\" and \"1 / height\"\n * - \"r\" parameter control where \"focused\" horizontal line lies\n */\n\nTHREE.VerticalTiltShiftShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"v\":        { type: \"f\", value: 1.0 / 512.0 },\n\t\t\"r\":        { type: \"f\", value: 0.35 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\t\t\"uniform float v;\",\n\t\t\"uniform float r;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vec4 sum = vec4( 0.0 );\",\n\n\t\t\t\"float vv = v * abs( r - vUv.y );\",\n\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 4.0 * vv ) ) * 0.051;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 3.0 * vv ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 2.0 * vv ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y - 1.0 * vv ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y ) ) * 0.1633;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 1.0 * vv ) ) * 0.1531;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 2.0 * vv ) ) * 0.12245;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 3.0 * vv ) ) * 0.0918;\",\n\t\t\t\"sum += texture2D( tDiffuse, vec2( vUv.x, vUv.y + 4.0 * vv ) ) * 0.051;\",\n\n\t\t\t\"gl_FragColor = sum;\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/js/lib/shaders/VignetteShader.js",
    "content": "/**\n * @author alteredq / http://alteredqualia.com/\n *\n * Vignette shader\n * based on PaintEffect postprocess from ro.me\n * http://code.google.com/p/3-dreams-of-black/source/browse/deploy/js/effects/PaintEffect.js\n */\n\nTHREE.VignetteShader = {\n\n\tuniforms: {\n\n\t\t\"tDiffuse\": { type: \"t\", value: null },\n\t\t\"offset\":   { type: \"f\", value: 1.0 },\n\t\t\"darkness\": { type: \"f\", value: 1.0 }\n\n\t},\n\n\tvertexShader: [\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t\"vUv = uv;\",\n\t\t\t\"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\n\n\t\t\"}\"\n\n\t].join( \"\\n\" ),\n\n\tfragmentShader: [\n\n\t\t\"uniform float offset;\",\n\t\t\"uniform float darkness;\",\n\n\t\t\"uniform sampler2D tDiffuse;\",\n\n\t\t\"varying vec2 vUv;\",\n\n\t\t\"void main() {\",\n\n\t\t\t// Eskil's vignette\n\n\t\t\t\"vec4 texel = texture2D( tDiffuse, vUv );\",\n\t\t\t\"vec2 uv = ( vUv - vec2( 0.5 ) ) * vec2( offset );\",\n\t\t\t\"gl_FragColor = vec4( mix( texel.rgb, vec3( 1.0 - darkness ), dot( uv, uv ) ), texel.a );\",\n\n\t\t\t/*\n\t\t\t// alternative version from glfx.js\n\t\t\t// this one makes more \"dusty\" look (as opposed to \"burned\")\n\n\t\t\t\"vec4 color = texture2D( tDiffuse, vUv );\",\n\t\t\t\"float dist = distance( vUv, vec2( 0.5 ) );\",\n\t\t\t\"color.rgb *= smoothstep( 0.8, offset * 0.799, dist *( darkness + offset ) );\",\n\t\t\t\"gl_FragColor = color;\",\n\t\t\t*/\n\n\t\t\"}\"\n\n\t].join( \"\\n\" )\n\n};\n"
  },
  {
    "path": "example/meshrender-collision.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var controls, camera, scene, renderer, proton;\n    var cameraCube, sceneCube;\n    var textureEquirec, textureCube, textureSphere;\n    var cubeMesh, sphereMesh;\n    var sphereMaterial;\n    var refract;\n\n    init();\n    function init() {\n        initScene();\n        addControls();\n        createProton();\n        animate();\n    }\n\n    function initScene() {\n        // CAMERAS\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100000);\n        camera.position.set(0, 0, 1000);\n        cameraCube = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100000);\n\n        // SCENE\n        scene = new THREE.Scene();\n        sceneCube = new THREE.Scene();\n        // Lights\n        var ambient = new THREE.AmbientLight(0xffffff);\n        scene.add(ambient);\n        // Textures\n        var r = \"img/cube/\";\n        var urls = [r + \"posx.jpg\", r + \"negx.jpg\",\n            r + \"posy.jpg\", r + \"negy.jpg\",\n            r + \"posz.jpg\", r + \"negz.jpg\"\n        ];\n        textureCube = new THREE.CubeTextureLoader().load(urls);\n        textureCube.format = THREE.RGBFormat;\n        textureCube.mapping = THREE.CubeReflectionMapping;\n        var textureLoader = new THREE.TextureLoader();\n        textureEquirec = textureLoader.load(\"img/cube/2294472375_24a3b8ef46_o.jpg\");\n        textureEquirec.mapping = THREE.EquirectangularReflectionMapping;\n        textureEquirec.magFilter = THREE.LinearFilter;\n        textureEquirec.minFilter = THREE.LinearMipMapLinearFilter;\n        textureSphere = textureLoader.load(\"img/cube/metal.jpg\");\n        textureSphere.mapping = THREE.SphericalReflectionMapping;\n        // Materials\n        var equirectShader = THREE.ShaderLib[\"equirect\"];\n        var equirectMaterial = new THREE.ShaderMaterial({\n            fragmentShader: equirectShader.fragmentShader,\n            vertexShader: equirectShader.vertexShader,\n            uniforms: equirectShader.uniforms,\n            depthWrite: false,\n            side: THREE.BackSide\n        });\n        equirectMaterial.uniforms[\"tEquirect\"].value = textureEquirec;\n        var cubeShader = THREE.ShaderLib[\"cube\"];\n        var cubeMaterial = new THREE.ShaderMaterial({\n            fragmentShader: cubeShader.fragmentShader,\n            vertexShader: cubeShader.vertexShader,\n            uniforms: cubeShader.uniforms,\n            depthWrite: false,\n            side: THREE.BackSide\n        });\n        cubeMaterial.uniforms[\"tCube\"].value = textureCube;\n        // Skybox\n        cubeMesh = new THREE.Mesh(new THREE.BoxGeometry(100, 100, 100), cubeMaterial);\n        sceneCube.add(cubeMesh);\n        //\n        var geometry = new THREE.SphereGeometry(100.0, 24, 24);\n        sphereMaterial = new THREE.MeshLambertMaterial({\n            envMap: textureCube\n        });\n        sphereMesh = new THREE.Mesh(geometry, sphereMaterial);\n        //scene.add(sphereMesh);\n        //\n        renderer = new THREE.WebGLRenderer();\n        renderer.autoClear = false;\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        renderer.setFaceCulling(THREE.CullFaceNone);\n        document.body.appendChild(renderer.domElement);\n\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n    }\n\n    function createProton() {\n        proton = new Proton;\n        var emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(2, 5), new Proton.Span(.5, 1));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(100));\n        emitter.addInitialize(new Proton.Life(5, 6));\n        emitter.addInitialize(new Proton.Body(sphereMesh));\n        emitter.addInitialize(new Proton.V(new Proton.Span(300, 500), new Proton.Vector3D(0, 1, 0), 30));\n        //emitter.addBehaviour(new Proton.Alpha(1, 0));\n        emitter.addBehaviour(new Proton.Scale(1));\n        emitter.addBehaviour(new Proton.Gravity(4));\n        emitter.addBehaviour(new Proton.Collision(emitter));\n\n        emitter.emit();\n        proton.addEmitter(emitter);\n        proton.addRender(new Proton.MeshRender(scene));\n    }\n\n    function onWindowResize() {\n        camera.aspect = window.innerWidth / window.innerHeight;\n        camera.updateProjectionMatrix();\n        cameraCube.aspect = window.innerWidth / window.innerHeight;\n        cameraCube.updateProjectionMatrix();\n        renderer.setSize(window.innerWidth, window.innerHeight);\n    }\n    //\n    function animate() {\n        requestAnimationFrame(animate);\n        render();\n        controls.update();\n    }\n\n    function render() {\n        var timer = -0.0002 * Date.now();\n        camera.lookAt(scene.position);\n        cameraCube.rotation.copy(camera.rotation);\n        renderer.render(sceneCube, cameraCube);\n        renderer.render(scene, camera);\n        proton.update();\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/meshrender-emitter.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, spring, controls;\n\n    init();\n\n    function init() {\n        initScene();\n        initLights();\n        initProton();\n        initControls();\n        addStats();\n        animate();\n    }\n\n    function initScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function initLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function initControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n        //controls.addEventListener('change', render);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function initProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n        proton.addRender(new Proton.MeshRender(scene));\n    }\n\n    function createBox() {\n        var geometry = new THREE.BoxGeometry(20, 20, 20);\n        var material = new THREE.MeshLambertMaterial({\n            color: \"#00ffcc\"\n        });\n\n        return new THREE.Mesh(geometry, material);\n    }\n\n\n    function createEmitter() {\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(6, 12), new Proton.Span(.2, .5));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(100));\n        emitter.addInitialize(new Proton.Life(2, 4));\n        emitter.addInitialize(new Proton.Body(createBox()));\n\n        emitter.addInitialize(new Proton.Velocity(300, new Proton.Vector3D(0, 1, 0), 50));\n\n        // //emitter.addBehaviour(new Proton.RandomDrift(30, 30, 30, .05));\n        emitter.addBehaviour(new Proton.Rotate(\"random\", \"random\"));\n        emitter.addBehaviour(new Proton.Scale(1, .1));\n        // emitter.addBehaviour(new Proton.Alpha(1, 0, Infinity, Proton.easeInQuart));\n        var zone2 = new Proton.BoxZone(500);\n        //emitter.addBehaviour(new Proton.CrossZone(zone2, \"bound\"));\n        spring = new Proton.Spring(100, 100, 100);\n        emitter.addBehaviour(spring);\n        emitter.addBehaviour(new Proton.Color('random', 'random', Infinity, Proton.easeOutQuart));\n\n        emitter.p.x = 0;\n        emitter.p.y = 0;\n        emitter.emit();\n\n        ///Proton.Debug.drawZone(proton,scene,zone2);\n        Proton.Debug.drawEmitter(proton, scene, emitter);\n        return emitter;\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    var tha = 0,\n        R = 200;\n\n    function render() {\n        proton.update(clock.getDelta());\n        renderer.render(scene, camera);\n\n        tha += .005;\n        proton.emitters[0].p.x = Math.cos(tha) * R;\n        proton.emitters[0].p.y = Math.sin(tha) * R;\n        proton.emitters[0].rotation.x += 0.01;\n        var x = Math.cos(tha) * 100;\n        var y = Math.sin(tha) * 100;\n        spring.reset(x, y, 100);\n        controls.update();\n\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/meshzone.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>three.proton - meshzone</title>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\" />\n    <style type=\"text/css\">\n      body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n      }\n    </style>\n  </head>\n\n  <body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script>\n      var proton, emitter;\n      var camera, scene, renderer, stats, clock, spring;\n      var mesh, randomBehaviour, gravity;\n\n      loadModel(initAll);\n\n      function initAll() {\n        initScene();\n        initLights();\n        initProton();\n        addStats();\n        addStars();\n        addMouseEvent();\n        animate();\n      }\n\n      function initScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener(\"resize\", onWindowResize, false);\n      }\n\n      function initLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n      }\n\n      function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = \"absolute\";\n        stats.dom.style.left = \"0px\";\n        stats.dom.style.top = \"0px\";\n        container.appendChild(stats.dom);\n      }\n\n      function addStars() {\n        var geometry = new THREE.Geometry();\n        for (var i = 0; i < 10000; i++) {\n          var vertex = new THREE.Vector3();\n          vertex.x = THREE.Math.randFloatSpread(2000);\n          vertex.y = THREE.Math.randFloatSpread(2000);\n          vertex.z = THREE.Math.randFloatSpread(2000);\n          geometry.vertices.push(vertex);\n        }\n        var particles = new THREE.Points(\n          geometry,\n          new THREE.PointsMaterial({\n            color: 0x888888\n          })\n        );\n        scene.add(particles);\n      }\n\n      function initProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n        proton.addRender(new Proton.SpriteRender(scene));\n      }\n\n      //load model\n      function loadModel(callback) {\n        var objectLoader = new THREE.ObjectLoader();\n        objectLoader.load(\"assets/teapot.json\", function(obj) {\n          mesh = obj;\n          callback();\n        });\n      }\n\n      function createEmitter() {\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(11, 15), new Proton.Span(0.02));\n        //addInitialize\n        emitter.addInitialize(new Proton.Position(new Proton.MeshZone(mesh, 200)));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(26, 50));\n        emitter.addInitialize(new Proton.Life(1.5));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n\n        //addBehaviour\n        randomBehaviour = new Proton.RandomDrift(2, 2, 2);\n        gravity = new Proton.Gravity(0);\n        emitter.addBehaviour(customScaleBehaviour());\n        emitter.addBehaviour(gravity);\n        emitter.addBehaviour(randomBehaviour);\n        emitter.addBehaviour(new Proton.Color([\"#00aeff\", \"#0fa954\", \"#54396e\", \"#e61d5f\"]));\n        emitter.addBehaviour(new Proton.Color(\"random\"));\n\n        emitter.p.x = 0;\n        emitter.p.y = -120;\n        emitter.emit();\n\n        return emitter;\n      }\n\n      function customScaleBehaviour() {\n        return {\n          initialize: function(particle) {\n            particle.oldRadius = particle.radius;\n            particle.scale = 0;\n          },\n          applyBehaviour: function(particle) {\n            if (particle.energy >= 2 / 3) {\n              particle.scale = (1 - particle.energy) * 3;\n            } else if (particle.energy <= 1 / 3) {\n              particle.scale = particle.energy * 3;\n            }\n            particle.radius = particle.oldRadius * particle.scale;\n          }\n        };\n      }\n\n      function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n          map: map,\n          color: 0xff0000,\n          blending: THREE.AdditiveBlending,\n          fog: true\n        });\n        return new THREE.Sprite(material);\n      }\n\n      function addMouseEvent() {\n        var index = 0;\n        window.addEventListener(\"mousedown\", function(e) {\n          index++;\n          if (index % 3 == 1) {\n            randomBehaviour.reset(2, 0, 0.2);\n            gravity.reset(3.5);\n          } else if (index % 3 == 2) {\n            randomBehaviour.reset(10, 10, 10);\n            gravity.reset(0);\n          } else {\n            randomBehaviour.reset(2, 2, 2);\n            gravity.reset(0);\n          }\n        });\n      }\n\n      function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n      }\n\n      var tha = 0;\n\n      function render() {\n        proton.update();\n        renderer.render(scene, camera);\n\n        tha += 0.005;\n        camera.lookAt(scene.position);\n        camera.position.x = Math.sin(tha) * 500;\n        camera.position.z = Math.cos(tha) * 500;\n        Proton.Debug.renderInfo(proton, 3);\n      }\n\n      function onWindowResize() {}\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "example/spriterender-base.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, controls;\n\n    init();\n    function init() {\n        initScene();\n        initLights();\n        initProton();\n        addStats();\n        animate();\n    }\n\n    function initScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function initLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function initProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n        proton.addRender(new Proton.SpriteRender(scene));\n\n        //Proton.Debug.drawZone(proton,scene,zone2);\n        //Proton.Debug.drawEmitter(proton,scene,emitter);\n    }\n\n    function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            color: 0xff0000,\n            blending: THREE.AdditiveBlending,\n            fog: true\n        });\n        return new THREE.Sprite(material);\n    }\n\n\n    function createEmitter() {\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(5, 10), new Proton.Span(.1, .25));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(100));\n        emitter.addInitialize(new Proton.Life(2, 4));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n        emitter.addInitialize(new Proton.Position(new Proton.BoxZone(100)));\n        emitter.addInitialize(new Proton.Velocity(200, new Proton.Vector3D(0, 1, 1), 180));\n\n        // //emitter.addBehaviour(new Proton.RandomDrift(30, 30, 30, .05));\n        emitter.addBehaviour(new Proton.Rotate(\"random\", \"random\"));\n        emitter.addBehaviour(new Proton.Scale(1, 0.5));\n        emitter.addBehaviour(new Proton.Alpha(1, 0, Infinity, Proton.easeInQuart));\n        var zone2 = new Proton.BoxZone(400);\n        //emitter.addBehaviour(new Proton.CrossZone(zone2, \"bound\"));\n        //emitter.addBehaviour(new Proton.Collision(emitter,true));\n        emitter.addBehaviour(new Proton.Color(0xff0000, 'random', Infinity, Proton.easeOutQuart));\n\n        emitter.p.x = 0;\n        emitter.p.y = 0;\n        emitter.emit();\n        return emitter;\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    var tha = 0;\n\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        //controls.update();\n\n        camera.lookAt(scene.position);\n        tha += .02;\n        camera.position.x = Math.sin(tha) * 500;\n        camera.position.z = Math.cos(tha) * 500;\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/spriterender-colors.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>SpriteRender - colors</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, spring, controls;\n\n    init();\n\n    function init() {\n        addScene();\n        addControls();\n        addLights();\n        addProton();\n        addStats();\n        animate();\n    }\n\n    function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        var axisHelper = new THREE.AxisHelper(250);\n        scene.add(axisHelper);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer({\n            preserveDrawingBuffer: true\n        });\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n    }\n\n    function addLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function addProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n        proton.addRender(new Proton.SpriteRender(scene));\n    }\n\n    function createBox() {\n        var geometry = new THREE.DodecahedronGeometry(20);\n        var material = new THREE.MeshLambertMaterial({\n            color: \"#00ffcc\"\n        });\n\n        return new THREE.Mesh(geometry, material);\n    }\n\n\n    function createEmitter() {\n        var colors = ['#529B88', '#CDD180', '#FFFA32', '#FB6255', '#FB4A53', '#FF4E50', '#F9D423'];\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(3, 6), new Proton.Span(.05, .2));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(200, 400));\n        emitter.addInitialize(new Proton.Life(2, 4));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n        emitter.addInitialize(new Proton.Position(new Proton.ScreenZone(camera, renderer)));\n        emitter.addBehaviour(new Proton.Alpha(0, 1, Infinity, Proton.easeOutCubic));\n        emitter.addBehaviour(new Proton.Scale(2, 0, Infinity, Proton.easeOutCubic));\n        emitter.addBehaviour(new Proton.Color(colors, 'random'));\n        emitter.emit();\n        return emitter;\n    }\n\n    function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            color: 0xff0000,\n            blending: THREE.AdditiveBlending,\n            fog: true\n        });\n        return new THREE.Sprite(material);\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        controls.update();\n\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/spriterender-g.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, spring, controls;\n\n    init();\n    function init() {\n        addScene();\n        addControls();\n        addLights();\n        addStars();\n        addProton();\n        //addInteraction();\n        addStats();\n        animate();\n    }\n\n    function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n    }\n\n    function addLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function addStars() {\n        var geometry = new THREE.Geometry();\n        for (var i = 0; i < 10000; i++) {\n            var vertex = new THREE.Vector3();\n            vertex.x = THREE.Math.randFloatSpread(2000);\n            vertex.y = THREE.Math.randFloatSpread(2000);\n            vertex.z = THREE.Math.randFloatSpread(2000);\n            geometry.vertices.push(vertex);\n        }\n        var particles = new THREE.Points(geometry, new THREE.PointsMaterial({\n            color: 0x888888\n        }));\n        scene.add(particles);\n    }\n\n    function addProton() {\n        proton = new Proton();\n        proton.addEmitter(createEmitter());\n        proton.addRender(new Proton.SpriteRender(scene));\n    }\n\n    function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            color: 0xff0000,\n            blending: THREE.AdditiveBlending,\n            fog: true\n        });\n        return new THREE.Sprite(material);\n    }\n\n\n    function createEmitter() {\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(10, 15), new Proton.Span(.05, .1));\n        emitter.addInitialize(new Proton.Body(createSprite()));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Life(1, 3));\n        emitter.addInitialize(new Proton.Position(new Proton.SphereZone(20)));\n        emitter.addInitialize(new Proton.V(new Proton.Span(500, 800), new Proton.Vector3D(0, 1, 0), 30));\n        emitter.addBehaviour(new Proton.RandomDrift(10, 10, 10, .05));\n        //emitter.addBehaviour(new Proton.Alpha(1, 0.1));\n        emitter.addBehaviour(new Proton.Scale(new Proton.Span(2, 3.5), 0));\n        emitter.addBehaviour(new Proton.G(6));\n        emitter.addBehaviour(new Proton.Color('#FF0026', ['#ffff00', '#ffff11'], Infinity, Proton.easeOutSine));\n        emitter.p.x = 0;\n        emitter.p.y = -150;\n        emitter.emit();\n        return emitter;\n    }\n\n    function addInteraction() {\n        window.addEventListener('mousemove', onMouseMove, false);\n        var pos = {\n            x: 0,\n            y: 0\n        };\n\n        function onMouseMove(event) {\n            pos.x = event.clientX;\n            pos.y = event.clientY;\n            var target = Proton.THREEUtil.toSpacePos(pos, camera, renderer.domElement);\n            emitter.p.x += (target.x - emitter.p.x) / 10;\n            emitter.p.y += (target.y - emitter.p.y) / 10;\n            emitter.p.z += (target.z - emitter.p.z) / 10;\n        }\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    function render() {\n        proton.update(clock.getDelta());\n        renderer.render(scene, camera);\n        controls.update();\n\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/spriterender-pointzone.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script src=\"./js/lib/TrackballControls.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, spring, controls;\n    var color1, color2,\n        tha = 0,\n        hcolor = 0;\n\n    init();\n    function init() {\n        addScene();\n        addControls();\n        addLights();\n        addStars();\n        addProton();\n        //addInteraction();\n        addStats();\n        animate();\n    }\n\n    function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.Fog(0xffffff, 1, 10000);\n\n        clock = new THREE.Clock();\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addControls() {\n        controls = new THREE.TrackballControls(camera);\n        controls.rotateSpeed = 1.0;\n        controls.zoomSpeed = 1.2;\n        controls.panSpeed = 0.8;\n        controls.noZoom = false;\n        controls.noPan = false;\n        controls.staticMoving = true;\n        controls.dynamicDampingFactor = 0.3;\n    }\n\n    function addLights() {\n        var ambientLight = new THREE.AmbientLight(0x101010);\n        scene.add(ambientLight);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function addStars() {\n        var geometry = new THREE.Geometry();\n        for (var i = 0; i < 10000; i++) {\n            var vertex = new THREE.Vector3();\n            vertex.x = THREE.Math.randFloatSpread(2000);\n            vertex.y = THREE.Math.randFloatSpread(2000);\n            vertex.z = THREE.Math.randFloatSpread(2000);\n            geometry.vertices.push(vertex);\n        }\n        var particles = new THREE.Points(geometry, new THREE.PointsMaterial({\n            color: 0x888888\n        }));\n        scene.add(particles);\n    }\n\n    function addProton() {\n        proton = new Proton();\n\n        emitter = new Proton.Emitter();\n        //setRate\n        emitter.rate = new Proton.Rate(new Proton.Span(4, 16), new Proton.Span(.01));\n        //addInitialize\n        emitter.addInitialize(new Proton.Position(new Proton.PointZone(0, 0, 0)));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(6, 12));\n        emitter.addInitialize(new Proton.Life(3));\n        emitter.addInitialize(new Proton.V(45, new Proton.Vector3D(0, 1, 0), 180));\n        //addBehaviour\n        emitter.addBehaviour(new Proton.Alpha(1, 0));\n        emitter.addBehaviour(new Proton.Scale(.1, 1.3));\n\n        color1 = new THREE.Color();\n        color2 = new THREE.Color();\n        colorBehaviour = new Proton.Color(color1, color2);\n        emitter.addBehaviour(colorBehaviour);\n\n        emitter.emit();\n        //add emitter\n        proton.addEmitter(emitter);\n        proton.addRender(new Proton.SpriteRender(scene));\n    }\n\n    function createSprite() {\n        var map = new THREE.TextureLoader().load(\"./img/dot.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            color: 0xff0000,\n            blending: THREE.AdditiveBlending,\n            fog: true\n        });\n        return new THREE.Sprite(material);\n    }\n\n    function changeParticleColor() {\n        hcolor += .01;\n        color1.setHSL(hcolor - (hcolor >> 0), 1, .5);\n        color2.setHSL(hcolor - (hcolor >> 0) + .3, 1, .5);\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    function render() {\n        changeParticleColor();\n        protonUpdate();\n        renderer.render(scene, camera);\n        camera.lookAt(scene.position);\n        moveEmitter();\n        rotateCamera(camera);\n        \n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function protonUpdate(){\n        var delta = clock.getDelta();\n        delta < 5 / 60 && proton.update(delta);\n    }\n\n    function moveEmitter(){\n        tha += Math.PI / 150;\n        var p = 300 * Math.sin(2 * tha);\n        emitter.p.x = p * Math.cos(tha);\n        emitter.p.y = p * Math.sin(tha);\n        emitter.p.z = p * Math.tan(tha) / 2;\n    }\n\n    var ctha = 0;\n    var r = 500;\n    function rotateCamera(camera){\n        ctha += .016;\n        r = 300;\n        camera.position.x = Math.sin(ctha) * r;\n        camera.position.z = Math.cos(ctha) * r;\n        camera.position.y = Math.sin(ctha) * r;\n    }\n\n    function onWindowResize() {\n\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "example/spriterender-snow.html",
    "content": "<!DOCTYPE HTML>\n<html>\n\n<head>\n    <title>three.proton - helloworld</title>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0\">\n    <style type=\"text/css\">\n    body {\n        font-family: Monospace;\n        background-color: #fff;\n        margin: 0;\n        padding: 0;\n        overflow: hidden;\n    }\n    </style>\n</head>\n\n<body>\n    <div id=\"container\"></div>\n    <script src=\"../lib/stats.min.js\"></script>\n    <script src=\"../lib/three.min.js\"></script>\n    <script src=\"../build/three.proton.min.js\"></script>\n    <script>\n    var proton, emitter;\n    var camera, scene, renderer, stats, clock, mouseXpercent, mouseYpercent, cameraTarget;\n\n    init();\n    function init() {\n        addScene();\n        addLights();\n        addPlane();\n        addInteraction();\n        addProton();\n        addStats();\n        animate();\n    }\n\n    function addScene() {\n        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 3000);\n        camera.position.z = 500;\n        scene = new THREE.Scene();\n        scene.fog = new THREE.FogExp2(0xffffff, 1, 10000);\n\n        renderer = new THREE.WebGLRenderer();\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(window.innerWidth, window.innerHeight);\n\n        document.body.appendChild(renderer.domElement);\n        window.addEventListener('resize', onWindowResize, false);\n    }\n\n    function addLights() {\n        var spotLight = new THREE.SpotLight(0xffffff, .5);\n        spotLight.position.set(0, 500, 100);\n        scene.add(spotLight);\n        spotLight.lookAt(scene);\n\n        // var spotLightHelper = new THREE.SpotLightHelper(spotLight);\n        // scene.add(spotLightHelper);\n\n        var pointLight = new THREE.PointLight(0xffffff, 2, 1000, 1);\n        pointLight.position.set(0, 200, 200);\n        scene.add(pointLight);\n    }\n\n    function addPlane() {\n        var plane = new THREE.Mesh(\n            new THREE.PlaneGeometry(2000, 2000, 9, 24),\n            new THREE.MeshLambertMaterial({\n                color: \"#3c5887\",\n                fog: false\n            })\n        );\n\n        var planeGeometry = plane.geometry;\n        for (i = 0, l = planeGeometry.vertices.length; i < l; i++) {\n            var y = Math.floor(i / 10);\n            var x = i - (y * 10);\n            if (x == 4 || x == 5) {\n                planeGeometry.vertices[i].z = 0;\n            } else {\n                planeGeometry.vertices[i].z = (Math.random() * 480) - 240;\n            }\n            if (y == 0 || y == 24) {\n                planeGeometry.vertices[i].z = -60;\n            }\n        }\n\n        plane.rotation.x = -Math.PI / 3;\n        plane.position.y = -200;\n        scene.add(plane);\n    }\n\n    function addStats() {\n        stats = new Stats();\n        stats.showPanel(0);\n        stats.dom.style.position = 'absolute';\n        stats.dom.style.left = '0px';\n        stats.dom.style.top = '0px';\n        container.appendChild(stats.dom);\n    }\n\n    function addProton() {\n        proton = new Proton();\n\n        emitter = new Proton.Emitter();\n        emitter.rate = new Proton.Rate(new Proton.Span(34, 48), new Proton.Span(.2, .5));\n        emitter.addInitialize(new Proton.Mass(1));\n        emitter.addInitialize(new Proton.Radius(new Proton.Span(10, 20)));\n\n        var position = new Proton.Position();\n        position.addZone(new Proton.BoxZone(2500, 10, 2500));\n        emitter.addInitialize(position);\n\n        emitter.addInitialize(new Proton.Life(5, 10));\n        emitter.addInitialize(new Proton.Body(createSnow()));\n        emitter.addInitialize(new Proton.Velocity(0, new Proton.Vector3D(0, -1, 0), 90));\n\n        emitter.addBehaviour(new Proton.RandomDrift(10, 1, 10, .05));\n        emitter.addBehaviour(new Proton.Rotate(\"random\", \"random\"));\n        emitter.addBehaviour(new Proton.Gravity(2));\n\n        var sceenZone = new Proton.ScreenZone(camera, renderer, 20, \"234\");\n        emitter.addBehaviour(new Proton.CrossZone(sceenZone, \"dead\"));\n\n        emitter.p.x = 0;\n        emitter.p.y = 800;\n        emitter.emit();\n\n        proton.addEmitter(emitter);\n        proton.addRender(new Proton.SpriteRender(scene));\n\n        //Proton.Debug.drawZone(proton,scene,new Proton.BoxZone(800, 10, 800));\n    }\n\n    function createSnow() {\n        var map = new THREE.TextureLoader().load(\"./img/snow.png\");\n        var material = new THREE.SpriteMaterial({\n            map: map,\n            transparent: true,\n            opacity: .5,\n            color: 0xffffff\n        });\n        return new THREE.Sprite(material);\n    }\n\n    function initInteraction() {\n        window.addEventListener('mousemove', onMouseMove, false);\n        var pos = {\n            x: 0,\n            y: 0\n        };\n\n        function onMouseMove(event) {\n            pos.x = event.clientX;\n            pos.y = event.clientY;\n            var target = Proton.THREEUtil.toSpacePos(pos, camera, renderer.domElement);\n            emitter.p.x += (target.x - emitter.p.x) / 10;\n            emitter.p.y += (target.y - emitter.p.y) / 10;\n            emitter.p.z += (target.z - emitter.p.z) / 10;\n        }\n    }\n\n    function animate() {\n        stats.begin();\n        requestAnimationFrame(animate);\n        render();\n        stats.end();\n    }\n\n    function render() {\n        proton.update();\n        renderer.render(scene, camera);\n        controlCamera();\n        Proton.Debug.renderInfo(proton, 3);\n    }\n\n    function addInteraction() {\n        document.addEventListener('mousemove', onDocumentMouseMove, false);\n        document.addEventListener('touchmove', onTouchMove, false);\n\n        mouseXpercent = mouseYpercent = 0;\n        cameraTarget = new THREE.Vector3();\n\n        function onDocumentMouseMove(event) {\n            var windowHalfX = window.innerWidth >> 1;\n            var windowHalfY = window.innerHeight >> 1;\n\n            var mouseX = (event.clientX - windowHalfX);\n            var mouseY = (event.clientY - windowHalfY);\n\n            mouseXpercent = mouseX / windowHalfX;\n            mouseYpercent = mouseY / windowHalfY;\n        }\n\n        function onTouchMove(event) {\n            event.preventDefault();\n            onDocumentMouseMove(event.touches[0]);\n        }\n    }\n\n    function controlCamera() {\n        cameraTarget.y += (((camera.position.y + 80) - mouseYpercent * 120) - cameraTarget.y) / 20;\n        cameraTarget.x += (mouseXpercent * 400 - cameraTarget.x) / 20;\n        camera.lookAt(cameraTarget);\n    }\n\n    function onWindowResize() {\n        camera.aspect = window.innerWidth / window.innerHeight;\n        camera.updateProjectionMatrix();\n        renderer.setSize(window.innerWidth, window.innerHeight);\n        //controls.handleResize();\n    }\n    </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "lib/config.js",
    "content": "var configArr = [\"../lib/domReady\"];\nvar configObj = { baseUrl: \"../src/\" };\nvar shim = {};\n\nvar paths = {\n    \"Proton\": \"core/Proton\",\n    \"EventDispatcher\": \"events/EventDispatcher\",\n    \"Util\": \"utils/Util\",\n    \"PUID\": \"utils/PUID\",\n    \"ColorUtil\": \"utils/ColorUtil\",\n    \"THREEUtil\": \"utils/THREEUtil\",\n    \"Particle\": \"core/Particle\",\n    \"Pool\": \"core/Pool\",\n\n    \"MathUtils\": \"math/MathUtils\",\n    \"Integration\": \"math/Integration\",\n    \"Vector3D\": \"math/Vector3D\",\n    \"Polar3D\": \"math/Polar3D\",\n    \"Quaternion\": \"math/Quaternion\",\n    \"Span\": \"math/Span\",\n    \"ArraySpan\": \"math/ArraySpan\",\n    \"Behaviour\": \"behaviour/Behaviour\",\n\n    \"Rate\": \"initialize/Rate\",\n    \"Initialize\": \"initialize/Initialize\",\n    \"InitializeUtil\": \"initialize/InitializeUtil\",\n    \"Life\": \"initialize/Life\",\n    \"Position\": \"initialize/Position\",\n    \"Velocity\": \"initialize/Velocity\",\n    \"Mass\": \"initialize/Mass\",\n    \"Radius\": \"initialize/Radius\",\n    \"Body\": \"initialize/Body\",\n\n    \"Force\": \"behaviour/Force\",\n    \"Attraction\": \"behaviour/Attraction\",\n    \"RandomDrift\": \"behaviour/RandomDrift\",\n    \"Repulsion\": \"behaviour/Repulsion\",\n    \"Gravity\": \"behaviour/Gravity\",\n    \"Collision\": \"behaviour/Collision\",\n    \"CrossZone\": \"behaviour/CrossZone\",\n    \"Alpha\": \"behaviour/Alpha\",\n    \"Scale\": \"behaviour/Scale\",\n    \"Rotate\": \"behaviour/Rotate\",\n    \"Color\": \"behaviour/Color\",\n    \"Spring\": \"behaviour/Spring\",\n\n    \"Emitter\": \"emitter/Emitter\",\n    \"BehaviourEmitter\": \"emitter/BehaviourEmitter\",\n    \"FollowEmitter\": \"emitter/FollowEmitter\",\n\n    \"ease\": \"ease/ease\",\n\n    \"BaseRender\": \"render/BaseRender\",\n    \"MeshRender\": \"render/MeshRender\",\n    \"SpriteRender\": \"render/SpriteRender\",\n    \"CustomRender\": \"render/CustomRender\",\n\n    \"Zone\": \"zone/Zone\",\n    \"LineZone\": \"zone/LineZone\",\n    \"SphereZone\": \"zone/SphereZone\",\n    \"PointZone\": \"zone/PointZone\",\n    \"BoxZone\": \"zone/BoxZone\",\n    \"ScreenZone\": \"zone/ScreenZone\",\n    \"MeshZone\": \"zone/MeshZone\",\n\n    \"log\": \"debug/log\",\n    \"Debug\": \"debug/Debug\"\n}\n\nfor (var index in paths) {\n    configArr.push(index);\n\n    //*****************Proton*****************//\n    if (index == \"Proton\") {\n        shim[index] = {\n            exports: \"Proton\"\n        };\n    }\n    //*****************math*****************//\n    else if (index == \"Span\") {\n        shim[index] = {\n            deps: [\"Proton\", \"MathUtils\"]\n        };\n    } else if (index == \"ArraySpan\" || index == \"SpanAB\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Span\"]\n        };\n    } else if (index == \"Polar3D\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Vector3D\"]\n        };\n    } else if (index == \"Integration\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\"]\n        };\n    }\n    //*****************util*****************//\n    else if (index == \"Util\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Vector3D\"]\n        };\n    }\n    //*****************core*****************//\n    else if (index == \"Particle\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Vector3D\", \"Util\"]\n        };\n    } else if (index == \"ParticlePool\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Particle\"]\n        };\n    }\n    //*****************emitter*****************//\n    else if (index == \"Emitter\") {\n        shim[index] = {\n            deps: [\"Proton\", \"InitializeUtil\", \"Util\", \"EventDispatcher\", \"Particle\", \"Rate\"]\n        };\n    } else if (index == \"BehaviourEmitter\" || index == \"FollowEmitter\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Emitter\"]\n        };\n    }\n    //*****************initialize*****************//\n    else if (index == \"InitializeUtil\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\"]\n        };\n    } else if (index == \"Initialize\") {\n        shim[index] = {\n            deps: [\"Proton\", \"InitializeUtil\"]\n        };\n    } else if (index == \"Color\" || index == \"Radius\" || index == \"Life\" || index == \"Mass\" || index == \"Position\" || index == \"Rate\" || index == \"Body\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Initialize\", \"ColorUtil\"]\n        };\n    } else if (index == \"Velocity\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Initialize\", \"Vector3D\"]\n        };\n    } else if (index == \"Spring\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Initialize\"]\n        };\n    }\n    \n    //*****************behaviour*****************//\n    else if (index == \"Behaviour\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\"]\n        };\n    } else if (index == \"CrossZone\" || index == \"Attraction\" || index == \"Collision\" || index == \"Force\" || index == \"CrossZone\" || index == \"RandomDrift\" || index == \"Scale\" || index == \"Alpha\" || index == \"Rotate\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Behaviour\", \"Vector3D\"]\n        };\n    } else if (index == \"Gravity\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Force\"]\n        };\n    } else if (index == \"Repulsion\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Attraction\"]\n        };\n    }\n    //*****************zone*****************//\n    else if (index == \"Zone\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Vector3D\", \"THREEUtil\"]\n        };\n    } else if (index == \"SphereZone\" || index == \"LineZone\" || index == \"PointZone\" || index == \"ScreenZone\" || index == \"MeshZone\" || index == \"BoxZone\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"Zone\"]\n        };\n    }\n    //*****************render*****************//\n    else if (index == \"BaseRender\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\"]\n        };\n    } else if (index == \"MeshRender\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"BaseRender\"]\n        };\n    } else if (index == \"SpriteRender\") {\n        shim[index] = {\n            deps: [\"MeshRender\"]\n        };\n    } else if (index == \"CustomRender\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\", \"BaseRender\"]\n        };\n    } else if (index == \"Debug\") {\n        shim[index] = {\n            deps: [\"Proton\", \"Util\"]\n        };\n    } else {\n        //EventDispatcher\\Vector3D\\MathUtils\\BaseRender\\Rectangle\\all-plus\n        shim[index] = {\n            deps: [\"Proton\"]\n        };\n    }\n}\n\nconfigObj.paths = paths;\nconfigObj.shim = shim;\nconfigObj.out = 'Proton.js';\nconfigObj.urlArgs = 'bust=' + Math.random();\nrequire.config(configObj);\nrequire(configArr, function(domReady, Proton) {\n    domReady(function() {\n        init(Proton);\n    });\n});\n"
  },
  {
    "path": "lib/domReady.js",
    "content": "/**\n * @license RequireJS domReady 2.0.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n * Available via the MIT or new BSD license.\n * see: http://github.com/requirejs/domReady for details\n */\n/*jslint */\n/*global require: false, define: false, requirejs: false,\n  window: false, clearInterval: false, document: false,\n  self: false, setInterval: false */\n\n\ndefine(function () {\n    'use strict';\n\n    var isTop, testDiv, scrollIntervalId,\n        isBrowser = typeof window !== \"undefined\" && window.document,\n        isPageLoaded = !isBrowser,\n        doc = isBrowser ? document : null,\n        readyCalls = [];\n\n    function runCallbacks(callbacks) {\n        var i;\n        for (i = 0; i < callbacks.length; i += 1) {\n            callbacks[i](doc);\n        }\n    }\n\n    function callReady() {\n        var callbacks = readyCalls;\n\n        if (isPageLoaded) {\n            //Call the DOM ready callbacks\n            if (callbacks.length) {\n                readyCalls = [];\n                runCallbacks(callbacks);\n            }\n        }\n    }\n\n    /**\n     * Sets the page as loaded.\n     */\n    function pageLoaded() {\n        if (!isPageLoaded) {\n            isPageLoaded = true;\n            if (scrollIntervalId) {\n                clearInterval(scrollIntervalId);\n            }\n\n            callReady();\n        }\n    }\n\n    if (isBrowser) {\n        if (document.addEventListener) {\n            //Standards. Hooray! Assumption here that if standards based,\n            //it knows about DOMContentLoaded.\n            document.addEventListener(\"DOMContentLoaded\", pageLoaded, false);\n            window.addEventListener(\"load\", pageLoaded, false);\n        } else if (window.attachEvent) {\n            window.attachEvent(\"onload\", pageLoaded);\n\n            testDiv = document.createElement('div');\n            try {\n                isTop = window.frameElement === null;\n            } catch (e) {}\n\n            //DOMContentLoaded approximation that uses a doScroll, as found by\n            //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/,\n            //but modified by other contributors, including jdalton\n            if (testDiv.doScroll && isTop && window.external) {\n                scrollIntervalId = setInterval(function () {\n                    try {\n                        testDiv.doScroll();\n                        pageLoaded();\n                    } catch (e) {}\n                }, 30);\n            }\n        }\n\n        //Check if document already complete, and if so, just trigger page load\n        //listeners. Latest webkit browsers also use \"interactive\", and\n        //will fire the onDOMContentLoaded before \"interactive\" but not after\n        //entering \"interactive\" or \"complete\". More details:\n        //http://dev.w3.org/html5/spec/the-end.html#the-end\n        //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded\n        //Hmm, this is more complicated on further use, see \"firing too early\"\n        //bug: https://github.com/requirejs/domReady/issues/1\n        //so removing the || document.readyState === \"interactive\" test.\n        //There is still a window.onload binding that should get fired if\n        //DOMContentLoaded is missed.\n        if (document.readyState === \"complete\") {\n            pageLoaded();\n        }\n    }\n\n    /** START OF PUBLIC API **/\n\n    /**\n     * Registers a callback for DOM ready. If DOM is already ready, the\n     * callback is called immediately.\n     * @param {Function} callback\n     */\n    function domReady(callback) {\n        if (isPageLoaded) {\n            callback(doc);\n        } else {\n            readyCalls.push(callback);\n        }\n        return domReady;\n    }\n\n    domReady.version = '2.0.1';\n\n    /**\n     * Loader Plugin API method\n     */\n    domReady.load = function (name, req, onLoad, config) {\n        if (config.isBuild) {\n            onLoad(null);\n        } else {\n            domReady(onLoad);\n        }\n    };\n\n    /** END OF PUBLIC API **/\n\n    return domReady;\n});"
  },
  {
    "path": "lib/require.js",
    "content": "/*\n RequireJS 2.1.4 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD license.\n see: http://github.com/jrburke/requirejs for details\n*/\nvar requirejs,require,define;\n(function(Y){function I(b){return\"[object Function]\"===L.call(b)}function J(b){return\"[object Array]\"===L.call(b)}function x(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function M(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function r(b,c){return da.call(b,c)}function i(b,c){return r(b,c)&&b[c]}function E(b,c){for(var d in b)if(r(b,d)&&c(b[d],d))break}function Q(b,c,d,i){c&&E(c,function(c,h){if(d||!r(b,h))i&&\"string\"!==typeof c?(b[h]||(b[h]={}),Q(b[h],\nc,d,i)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function Z(b){if(!b)return b;var c=Y;x(b.split(\".\"),function(b){c=c[b]});return c}function F(b,c,d,i){c=Error(c+\"\\nhttp://requirejs.org/docs/errors.html#\"+b);c.requireType=b;c.requireModules=i;d&&(c.originalError=d);return c}function ea(b){function c(a,f,v){var e,n,b,c,d,k,g,h=f&&f.split(\"/\");e=h;var l=m.map,j=l&&l[\"*\"];if(a&&\".\"===a.charAt(0))if(f){e=i(m.pkgs,f)?h=[f]:h.slice(0,h.length-1);f=a=e.concat(a.split(\"/\"));\nfor(e=0;f[e];e+=1)if(n=f[e],\".\"===n)f.splice(e,1),e-=1;else if(\"..\"===n)if(1===e&&(\"..\"===f[2]||\"..\"===f[0]))break;else 0<e&&(f.splice(e-1,2),e-=2);e=i(m.pkgs,f=a[0]);a=a.join(\"/\");e&&a===f+\"/\"+e.main&&(a=f)}else 0===a.indexOf(\"./\")&&(a=a.substring(2));if(v&&(h||j)&&l){f=a.split(\"/\");for(e=f.length;0<e;e-=1){b=f.slice(0,e).join(\"/\");if(h)for(n=h.length;0<n;n-=1)if(v=i(l,h.slice(0,n).join(\"/\")))if(v=i(v,b)){c=v;d=e;break}if(c)break;!k&&(j&&i(j,b))&&(k=i(j,b),g=e)}!c&&k&&(c=k,d=g);c&&(f.splice(0,d,\nc),a=f.join(\"/\"))}return a}function d(a){z&&x(document.getElementsByTagName(\"script\"),function(f){if(f.getAttribute(\"data-requiremodule\")===a&&f.getAttribute(\"data-requirecontext\")===k.contextName)return f.parentNode.removeChild(f),!0})}function y(a){var f=i(m.paths,a);if(f&&J(f)&&1<f.length)return d(a),f.shift(),k.require.undef(a),k.require([a]),!0}function g(a){var f,b=a?a.indexOf(\"!\"):-1;-1<b&&(f=a.substring(0,b),a=a.substring(b+1,a.length));return[f,a]}function h(a,f,b,e){var n,u,d=null,h=f?f.name:\nnull,l=a,m=!0,j=\"\";a||(m=!1,a=\"_@r\"+(L+=1));a=g(a);d=a[0];a=a[1];d&&(d=c(d,h,e),u=i(p,d));a&&(d?j=u&&u.normalize?u.normalize(a,function(a){return c(a,h,e)}):c(a,h,e):(j=c(a,h,e),a=g(j),d=a[0],j=a[1],b=!0,n=k.nameToUrl(j)));b=d&&!u&&!b?\"_unnormalized\"+(M+=1):\"\";return{prefix:d,name:j,parentMap:f,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(d?d+\"!\"+j:j)+b}}function q(a){var f=a.id,b=i(j,f);b||(b=j[f]=new k.Module(a));return b}function s(a,f,b){var e=a.id,n=i(j,e);if(r(p,e)&&(!n||n.defineEmitComplete))\"defined\"===\nf&&b(p[e]);else q(a).on(f,b)}function A(a,f){var b=a.requireModules,e=!1;if(f)f(a);else if(x(b,function(f){if(f=i(j,f))f.error=a,f.events.error&&(e=!0,f.emit(\"error\",a))}),!e)l.onError(a)}function w(){R.length&&(fa.apply(G,[G.length-1,0].concat(R)),R=[])}function B(a,f,b){var e=a.map.id;a.error?a.emit(\"error\",a.error):(f[e]=!0,x(a.depMaps,function(e,c){var d=e.id,h=i(j,d);h&&(!a.depMatched[c]&&!b[d])&&(i(f,d)?(a.defineDep(c,p[d]),a.check()):B(h,f,b))}),b[e]=!0)}function C(){var a,f,b,e,n=(b=1E3*m.waitSeconds)&&\nk.startTime+b<(new Date).getTime(),c=[],h=[],g=!1,l=!0;if(!T){T=!0;E(j,function(b){a=b.map;f=a.id;if(b.enabled&&(a.isDefine||h.push(b),!b.error))if(!b.inited&&n)y(f)?g=e=!0:(c.push(f),d(f));else if(!b.inited&&(b.fetched&&a.isDefine)&&(g=!0,!a.prefix))return l=!1});if(n&&c.length)return b=F(\"timeout\",\"Load timeout for modules: \"+c,null,c),b.contextName=k.contextName,A(b);l&&x(h,function(a){B(a,{},{})});if((!n||e)&&g)if((z||$)&&!U)U=setTimeout(function(){U=0;C()},50);T=!1}}function D(a){r(p,a[0])||\nq(h(a[0],null,!0)).init(a[1],a[2])}function H(a){var a=a.currentTarget||a.srcElement,b=k.onScriptLoad;a.detachEvent&&!V?a.detachEvent(\"onreadystatechange\",b):a.removeEventListener(\"load\",b,!1);b=k.onScriptError;(!a.detachEvent||V)&&a.removeEventListener(\"error\",b,!1);return{node:a,id:a&&a.getAttribute(\"data-requiremodule\")}}function K(){var a;for(w();G.length;){a=G.shift();if(null===a[0])return A(F(\"mismatch\",\"Mismatched anonymous define() module: \"+a[a.length-1]));D(a)}}var T,W,k,N,U,m={waitSeconds:7,\nbaseUrl:\"./\",paths:{},pkgs:{},shim:{},map:{},config:{}},j={},X={},G=[],p={},S={},L=1,M=1;N={require:function(a){return a.require?a.require:a.require=k.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return m.config&&i(m.config,a.map.id)||{}},exports:p[a.map.id]}}};W=function(a){this.events=i(X,a.id)||{};this.map=a;this.shim=\ni(m.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};W.prototype={init:function(a,b,c,e){e=e||{};if(!this.inited){this.factory=b;if(c)this.on(\"error\",c);else this.events.error&&(c=t(this,function(a){this.emit(\"error\",a)}));this.depMaps=a&&a.slice(0);this.errback=c;this.inited=!0;this.ignore=e.ignore;e.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,b){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=\nb)},fetch:function(){if(!this.fetched){this.fetched=!0;k.startTime=(new Date).getTime();var a=this.map;if(this.shim)k.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=this.map.url;S[a]||(S[a]=!0,k.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,b,c=this.map.id;b=this.depExports;var e=this.exports,n=this.factory;\nif(this.inited)if(this.error)this.emit(\"error\",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(I(n)){if(this.events.error)try{e=k.execCb(c,n,b,e)}catch(d){a=d}else e=k.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType=\"define\",A(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&&\n!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(k,this.map,this.depMaps);delete j[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit(\"defined\",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,\"defined\",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,g=k.makeRequire(a.parentMap,{enableBuildCallback:!0});\nif(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||\"\"),e=h(a.prefix+\"!\"+d,this.map.parentMap),s(e,\"defined\",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(j,e.id)){this.depMaps.push(e);if(this.events.error)d.on(\"error\",t(this,function(a){this.emit(\"error\",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=\n[b];E(j,function(a){0===a.map.id.indexOf(b+\"_unnormalized\")&&delete j[a.map.id]});A(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(j){return A(F(\"fromtexteval\",\"fromText eval for \"+b+\" failed: \"+j,j,[b]))}v&&(O=!0);this.depMaps.push(u);k.completeLoad(d);g([d],n)}),e.load(a.name,g,n,m)}));k.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a,\nb){var c,e;if(\"string\"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,\"defined\",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,\"error\",this.errback)}c=a.id;e=j[c];!r(N,c)&&(e&&!e.enabled)&&k.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(j,a.id);b&&!b.enabled&&k.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=\nthis.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});\"error\"===a&&delete this.events[a]}};k={config:m,contextName:b,registry:j,defined:p,urlFetched:S,defQueue:G,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&\"/\"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+=\"/\");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?\"map\"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a,\nb){J(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=k.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a=\"string\"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||\"main\").replace(ga,\"\").replace(aa,\"\")}}),m.pkgs=b);E(j,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)k.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments));\nreturn b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function g(e,c,u){var i,m;d.enableBuildCallback&&(c&&I(c))&&(c.__requireJsBuild=!0);if(\"string\"===typeof e){if(I(c))return A(F(\"requireargs\",\"Invalid require call\"),u);if(a&&r(N,e))return N[e](j[a.id]);if(l.get)return l.get(k,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?A(F(\"notloaded\",'Module name \"'+i+'\" has not been loaded yet for context: '+b+(a?\"\":\". Use require([])\"))):p[i]}K();k.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap;\nm.init(e,c,u,{enabled:!0});C()});return g}d=d||{};Q(g,{isBrowser:z,toUrl:function(b){var d,f=b.lastIndexOf(\".\"),h=b.split(\"/\")[0];if(-1!==f&&(!(\".\"===h||\"..\"===h)||1<f))d=b.substring(f,b.length),b=b.substring(0,f);b=k.nameToUrl(c(b,a&&a.id,!0),d||\".fake\");return d?b:b.substring(0,b.length-5)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(j,b)}});a||(g.undef=function(b){w();var c=h(b,a,!0),d=i(j,b);delete p[b];delete S[c.url];delete X[b];\nd&&(d.events.defined&&(X[b]=d.events),delete j[b])});return g},enable:function(a){i(j,a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();G.length;){c=G.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(j,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:A(F(\"nodefine\",\"No define call for \"+a,null,[a]));D([a,d.deps||[],d.exportsFn])}C()},nameToUrl:function(a,b){var c,d,h,g,k,j;if(l.jsExtRegExp.test(a))g=\na+(b||\"\");else{c=m.paths;d=m.pkgs;g=a.split(\"/\");for(k=g.length;0<k;k-=1)if(j=g.slice(0,k).join(\"/\"),h=i(d,j),j=i(c,j)){J(j)&&(j=j[0]);g.splice(0,k,j);break}else if(h){c=a===h.name?h.location+\"/\"+h.main:h.location;g.splice(0,k,c);break}g=g.join(\"/\");g+=b||(/\\?/.test(g)?\"\":\".js\");g=(\"/\"===g.charAt(0)||g.match(/^[\\w\\+\\.\\-]+:/)?\"\":m.baseUrl)+g}return m.urlArgs?g+((-1===g.indexOf(\"?\")?\"?\":\"&\")+m.urlArgs):g},load:function(a,b){l.load(k,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(\"load\"===\na.type||ha.test((a.currentTarget||a.srcElement).readyState))P=null,a=H(a),k.completeLoad(a.id)},onScriptError:function(a){var b=H(a);if(!y(b.id))return A(F(\"scripterror\",\"Script error\",a,[b.id]))}};k.require=k.makeRequire();return k}var l,w,B,D,s,H,P,K,ba,ca,ia=/(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,ja=/[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,aa=/\\.js$/,ga=/^\\.\\//;w=Object.prototype;var L=w.toString,da=w.hasOwnProperty,fa=Array.prototype.splice,z=!!(\"undefined\"!==typeof window&&navigator&&\ndocument),$=!z&&\"undefined\"!==typeof importScripts,ha=z&&\"PLAYSTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/,V=\"undefined\"!==typeof opera&&\"[object Opera]\"===opera.toString(),C={},q={},R=[],O=!1;if(\"undefined\"===typeof define){if(\"undefined\"!==typeof requirejs){if(I(requirejs))return;q=requirejs;requirejs=void 0}\"undefined\"!==typeof require&&!I(require)&&(q=require,require=void 0);l=requirejs=function(b,c,d,y){var g,h=\"_\";!J(b)&&\"string\"!==typeof b&&(g=b,J(c)?(b=c,c=d,d=y):b=[]);\ng&&g.context&&(h=g.context);(y=i(C,h))||(y=C[h]=l.s.newContext(h));g&&y.configure(g);return y.require(b,c,d)};l.config=function(b){return l(b)};l.nextTick=\"undefined\"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=l);l.version=\"2.1.4\";l.jsExtRegExp=/^\\/|:|\\?|\\.js$/;l.isBrowser=z;w=l.s={contexts:C,newContext:ea};l({});x([\"toUrl\",\"undef\",\"defined\",\"specified\"],function(b){l[b]=function(){var c=C._;return c.require[b].apply(c,arguments)}});if(z&&(B=w.head=document.getElementsByTagName(\"head\")[0],\nD=document.getElementsByTagName(\"base\")[0]))B=w.head=D.parentNode;l.onError=function(b){throw b;};l.load=function(b,c,d){var i=b&&b.config||{},g;if(z)return g=i.xhtml?document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"html:script\"):document.createElement(\"script\"),g.type=i.scriptType||\"text/javascript\",g.charset=\"utf-8\",g.async=!0,g.setAttribute(\"data-requirecontext\",b.contextName),g.setAttribute(\"data-requiremodule\",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf(\"[native code\"))&&\n!V?(O=!0,g.attachEvent(\"onreadystatechange\",b.onScriptLoad)):(g.addEventListener(\"load\",b.onScriptLoad,!1),g.addEventListener(\"error\",b.onScriptError,!1)),g.src=d,K=g,D?B.insertBefore(g,D):B.appendChild(g),K=null,g;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName(\"script\"),function(b){B||(B=b.parentNode);if(s=b.getAttribute(\"data-main\"))return q.baseUrl||(H=s.split(\"/\"),ba=H.pop(),ca=H.length?H.join(\"/\")+\"/\":\"./\",q.baseUrl=ca,s=ba),s=s.replace(aa,\"\"),q.deps=q.deps?q.deps.concat(s):\n[s],!0});define=function(b,c,d){var i,g;\"string\"!==typeof b&&(d=c,c=b,b=null);J(c)||(d=c,c=[]);!c.length&&I(d)&&d.length&&(d.toString().replace(ia,\"\").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?[\"require\"]:[\"require\",\"exports\",\"module\"]).concat(c));if(O){if(!(i=K))P&&\"interactive\"===P.readyState||M(document.getElementsByTagName(\"script\"),function(b){if(\"interactive\"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute(\"data-requiremodule\")),g=C[i.getAttribute(\"data-requirecontext\")])}(g?\ng.defQueue:R).push([b,c,d])};define.amd={jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this);\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"three.proton.js\",\n  \"version\": \"0.2.3\",\n  \"description\": \"three.proton is a magical 3d particle engine using [three.js]\",\n  \"main\": \"./build/three.proton.min.js\",\n  \"directories\": {\n    \"example\": \"example\",\n    \"lib\": \"lib\"\n  },\n  \"scripts\": {\n    \"build\": \"cd ./build && node build.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/drawcall/three.proton.git\"\n  },\n  \"keywords\": [\n    \"particle\",\n    \"three.js\",\n    \"threejs\",\n    \"3d-particle\"\n  ],\n  \"author\": \"drawcall\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/drawcall/three.proton/issues\"\n  },\n  \"homepage\": \"https://github.com/drawcall/three.proton#readme\"\n}\n"
  },
  {
    "path": "src/behaviour/Alpha.js",
    "content": "(function(Proton, undefined) {\n\n    /**\n     * The Alpha class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n\n    function Alpha(a, b, life, easing) {\n        Alpha._super_.call(this, life, easing);\n        this.reset(a, b);\n        /**\n         * The Proton.Behaviour name;\n         * @property name\n         * @type {string}\n         */\n        this.name = \"Alpha\";\n    }\n\n\n    Proton.Util.inherits(Alpha, Proton.Behaviour);\n    Alpha.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createSpan(Proton.Util.initValue(a, 1));\n        this.b = Proton.createSpan(b);\n        life && Alpha._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Alpha.prototype.initialize = function(particle) {\n        particle.useAlpha = true;\n        particle.transform.alphaA = this.a.getValue();\n        if (this._same)\n            particle.transform.alphaB = particle.transform.alphaA;\n        else\n            particle.transform.alphaB = this.b.getValue();\n    };\n\n    Alpha.prototype.applyBehaviour = function(particle, time, index) {\n        Alpha._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        particle.alpha = Proton.MathUtils.lerp(particle.transform.alphaA, particle.transform.alphaB, this.energy);\n        if (particle.alpha < 0.002) particle.alpha = 0;\n    };\n\n    Proton.Alpha = Alpha;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Attraction.js",
    "content": "(function(Proton, undefined) {\n\tfunction Attraction(targetPosition, force, radius, life, easing) {\n\t\tAttraction._super_.call(this, life, easing);\n\t\tthis.targetPosition = Proton.Util.initValue(targetPosition, new Proton.Vector3D);\n\t\tthis.radius = Proton.Util.initValue(radius, 1000);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tthis.radiusSq = this.radius * this.radius\n\t\tthis.attractionForce = new Proton.Vector3D();\n\t\tthis.lengthSq = 0;\n\t\tthis.name = \"Attraction\";\n\t}\n\n\n\tProton.Util.inherits(Attraction, Proton.Behaviour);\n\tAttraction.prototype.reset = function(targetPosition, force, radius, life, easing) {\n\t\tthis.targetPosition = Proton.Util.initValue(targetPosition, new Proton.Vector3D);\n\t\tthis.radius = Proton.Util.initValue(radius, 1000);\n\t\tthis.force = Proton.Util.initValue(this.normalizeValue(force), 100);\n\t\tthis.radiusSq = this.radius * this.radius\n\t\tthis.attractionForce = new Proton.Vector3D();\n\t\tthis.lengthSq = 0;\n\t\tif (life)\n\t\t\tAttraction._super_.prototype.reset.call(this, life, easing);\n\t}\n\n\tAttraction.prototype.applyBehaviour = function(particle, time, index) {\n\t\tAttraction._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\t\tthis.attractionForce.copy(this.targetPosition);\n\t\tthis.attractionForce.sub(particle.p);\n\t\tthis.lengthSq = this.attractionForce.lengthSq();\n\t\tif (this.lengthSq > 0.000004 && this.lengthSq < this.radiusSq) {\n\t\t\tthis.attractionForce.normalize();\n\t\t\tthis.attractionForce.scalar(1 - this.lengthSq / this.radiusSq);\n\t\t\tthis.attractionForce.scalar(this.force);\n\t\t\tparticle.a.add(this.attractionForce);\n\t\t}\n\t};\n\n\tProton.Attraction = Attraction;\n})(Proton);\n\n"
  },
  {
    "path": "src/behaviour/Behaviour.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Behaviour(life, easing) {\n        /**\n         * The behaviour's id;\n         * @property id\n         * @type {String} id\n         */\n        this.id = 'Behaviour_' + Behaviour.id++;\n        this.life = Proton.Util.initValue(life, Infinity);\n\n        /**\n         * The behaviour's decaying trend, for example Proton.easeOutQuart;\n         * @property easing\n         * @type {String}\n         * @default Proton.easeLinear\n         */\n        this.easing = Proton.Util.initValue(easing, Proton.ease.setEasingByName(Proton.ease.easeLinear));\n        this.age = 0;\n        this.energy = 1;\n        /**\n         * The behaviour is Dead;\n         * @property dead\n         * @type {Boolean}\n         */\n        this.dead = false;\n\n        /**\n         * The behaviour name;\n         * @property name\n         * @type {string}\n         */\n\n        this.name = 'Behaviour';\n    }\n\n    Behaviour.id = 0;\n\n\n    Behaviour.prototype = {\n        /**\n         * Reset this behaviour's parameters\n         *\n         * @method reset\n         * @param {Number} this behaviour's life\n         * @param {String} this behaviour's easing\n         */\n        reset: function(life, easing) {\n            this.life = Proton.Util.initValue(life, Infinity);\n            this.easing = Proton.Util.initValue(easing, Proton.ease.setEasingByName(Proton.ease.easeLinear));\n        },\n        /**\n         * Normalize a force by 1:100;\n         *\n         * @method normalizeForce\n         * @param {Proton.Vector2D} force \n         */\n        normalizeForce: function(force) {\n            return force.scalar(Proton.MEASURE);\n        },\n\n        /**\n         * Normalize a value by 1:100;\n         *\n         * @method normalizeValue\n         * @param {Number} value\n         */\n        normalizeValue: function(value) {\n            return value * Proton.MEASURE;\n        },\n\n        /**\n         * Initialize the behaviour's parameters for all particles\n         *\n         * @method initialize\n         * @param {Proton.Particle} particle\n         */\n        initialize: function(particle) {},\n\n        /**\n         * Apply this behaviour for all particles every time\n         *\n         * @method applyBehaviour\n         * @param {Proton.Particle} particle\n         * @param {Number} the integrate time 1/ms\n         * @param {Int} the particle index\n         */\n        applyBehaviour: function(particle, time, index) {\n            if (this.dead) return;\n\n            this.age += time;\n            if (this.age >= this.life) {\n                this.energy = 0;\n                this.dead = true;\n                return;\n            }\n\n            var scale = this.easing(particle.age / particle.life);\n            this.energy = Math.max(1 - scale, 0);\n        },\n\n        /**\n         * Destory this behaviour\n         * @method destroy\n         */\n        destroy: function() {\n\n        }\n    };\n\n    Proton.Behaviour = Behaviour;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Collision.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Scale class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n    //can use Collision(emitter,true,function(){}) or Collision();\n    function Collision(emitter, useMass, callback, life, easing) {\n        Collision._super_.call(this, life, easing);\n        this.reset(emitter, useMass, callback);\n        this.name = \"Collision\";\n    }\n\n    Proton.Util.inherits(Collision, Proton.Behaviour);\n    Collision.prototype.reset = function(emitter, useMass, callback, life, easing) {\n        this.emitter = emitter;\n        this.useMass = useMass;\n        this.callback = callback;\n        this.particles = [];\n        this.delta = new Proton.Vector3D();\n        life && Collision._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Collision.prototype.applyBehaviour = function(particle, time, index) {\n        var particles = this.emitter ? this.emitter.particles.slice(index) : this.particles.slice(index);\n        var otherParticle, lengthSq, overlap, distance;\n        var averageMass1, averageMass2;\n        \n        var i = particles.length;\n        while (i--) {\n            otherParticle = particles[i];\n            if (otherParticle == particle) continue;\n            \n            this.delta.copy(otherParticle.p).sub(particle.p);\n            lengthSq = this.delta.lengthSq();\n            distance = particle.radius + otherParticle.radius;\n\n            if (lengthSq <= distance * distance) {\n                overlap = distance - Math.sqrt(lengthSq);\n                overlap += 0.5;\n\n                averageMass1 = this._getAverageMass(particle, otherParticle);\n                averageMass2 = this._getAverageMass(otherParticle, particle);\n\n                particle.p.add(this.delta.clone().normalize().scalar(overlap * -averageMass1));\n                otherParticle.p.add(this.delta.normalize().scalar(overlap * averageMass2));\n\n                this.callback && this.callback(particle, otherParticle);\n            }\n        }\n    };\n\n    Collision.prototype._getAverageMass = function(aPartcile, bParticle) {\n        return this.useMass ? bParticle.mass / (aPartcile.mass + bParticle.mass) : 0.5;\n    }\n\n    Proton.Collision = Collision;\n\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Color.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Scale class is the base for the other Proton.Behaviour\n     *\n     * @class Proton.Behaviour\n     * @constructor\n     */\n    function Color(a, b, life, easing) {\n        Color._super_.call(this, life, easing);\n        this.reset(a, b);\n        this.name = \"Color\";\n    }\n\n\n    Proton.Util.inherits(Color, Proton.Behaviour);\n    Color.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createArraySpan(a);\n        this.b = Proton.createArraySpan(b);\n        life && Color._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Color.prototype.initialize = function(particle) {\n        particle.transform.colorA = Proton.ColorUtil.getRGB(this.a.getValue());\n\n        particle.useColor = true;\n        if (this._same)\n            particle.transform.colorB = particle.transform.colorA;\n        else\n            particle.transform.colorB = Proton.ColorUtil.getRGB(this.b.getValue());\n    };\n\n    Color.prototype.applyBehaviour = function(particle, time, index) {\n        Color._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        if (!this._same) {\n            particle.color.r = Proton.MathUtils.lerp(particle.transform.colorA.r, particle.transform.colorB.r, this.energy) ;\n            particle.color.g = Proton.MathUtils.lerp(particle.transform.colorA.g, particle.transform.colorB.g, this.energy) ;\n            particle.color.b = Proton.MathUtils.lerp(particle.transform.colorA.b, particle.transform.colorB.b, this.energy) ;\n        } else {\n            particle.color.r = particle.transform.colorA.r;\n            particle.color.g = particle.transform.colorA.g;\n            particle.color.b = particle.transform.colorA.b;\n        }\n    };\n\n\n    Proton.Color = Color;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/CrossZone.js",
    "content": "(function(Proton, undefined) {\n    function CrossZone(a, b, life, easing) {\n        CrossZone._super_.call(this, life, easing);\n        this.reset(a, b);\n        ///dead /bound /cross\n        this.name = \"CrossZone\";\n    }\n\n\n    Proton.Util.inherits(CrossZone, Proton.Behaviour);\n    CrossZone.prototype.reset = function(a, b, life, easing) {\n        var zone, crossType;\n        if (typeof a == \"string\") {\n            crossType = a;\n            zone = b;\n        } else {\n            crossType = b;\n            zone = a;\n        }\n        \n        this.zone = zone;\n        this.zone.crossType = Proton.Util.initValue(crossType, \"dead\");\n        if (life)\n            CrossZone._super_.prototype.reset.call(this, life, easing);\n    }\n\n    CrossZone.prototype.applyBehaviour = function(particle, time, index) {\n        CrossZone._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        this.zone.crossing.call(this.zone, particle);\n    };\n\n    Proton.CrossZone = CrossZone;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Force.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Force(fx, fy, fz, life, easing) {\n        Force._super_.call(this, life, easing);\n        Force.prototype.reset.call(this, fx, fy, fz);\n        this.name = \"Force\";\n    }\n\n    Proton.Util.inherits(Force, Proton.Behaviour);\n    Force.prototype.reset = function(fx, fy, fz) {\n        this.force = this.normalizeForce(new Proton.Vector3D(fx, fy, fz));\n        this.force.id = Math.random();\n    }\n\n    Force.prototype.applyBehaviour = function(particle, time, index) {\n        Force._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        particle.a.add(this.force);\n    };\n\n    Proton.F = Proton.Force = Force;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Gravity.js",
    "content": "(function(Proton, undefined) {\n    function Gravity(g, life, easing) {\n        Gravity._super_.call(this, 0, -g, 0, life, easing);\n        this.name = \"Gravity\";\n    }\n\n    Proton.Util.inherits(Gravity, Proton.Force);\n\n    Gravity.prototype.reset = function(g, life, easing) {\n        Gravity._super_.prototype.reset.call(this, 0, -g, 0, life, easing);\n    }\n\n    Proton.Gravity = Gravity;\n    Proton.G = Gravity;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/RandomDrift.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function RandomDrift(driftX, driftY, driftZ, delay, life, easing) {\n        RandomDrift._super_.call(this, life, easing);\n        this.reset(driftX, driftY, driftZ, delay);\n        this.time = 0;\n        this.name = \"RandomDrift\";\n    }\n\n\n    Proton.Util.inherits(RandomDrift, Proton.Behaviour);\n    RandomDrift.prototype.reset = function(driftX, driftY, driftZ, delay, life, easing) {\n        this.randomFoce = this.normalizeForce(new Proton.Vector3D(driftX, driftY, driftZ));\n        this.delayPan = Proton.createSpan(delay || .03);\n        this.time = 0;\n        life && RandomDrift._super_.prototype.reset.call(this, life, easing);\n    }\n\n    RandomDrift.prototype.applyBehaviour = function(particle, time, index) {\n        RandomDrift._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        this.time += time;\n        if (this.time >= this.delayPan.getValue()) {\n            var ax = Proton.MathUtils.randomAToB(-this.randomFoce.x, this.randomFoce.x);\n            var ay = Proton.MathUtils.randomAToB(-this.randomFoce.y, this.randomFoce.y);\n            var az = Proton.MathUtils.randomAToB(-this.randomFoce.z, this.randomFoce.z);\n            particle.a.addValue(ax, ay, az);\n            this.time = 0;\n        };\n    };\n\n    Proton.RandomDrift = RandomDrift;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Repulsion.js",
    "content": "(function(Proton, undefined) {\n\tfunction Repulsion(targetPosition, force, radius, life, easing) {\n\t\tRepulsion._super_.call(this, targetPosition, force, radius, life, easing);\n\t\tthis.force *= -1;\n\t\tthis.name = \"Repulsion\";\n\t}\n\n\n\tProton.Util.inherits(Repulsion, Proton.Attraction);\n\tRepulsion.prototype.reset = function(targetPosition, force, radius, life, easing) {\n\t\tRepulsion._super_.prototype.reset.call(this, targetPosition, force, radius, life, easing);\n\t\tthis.force *= -1;\n\t}\n\tProton.Repulsion = Repulsion;\n})(Proton);\n\n"
  },
  {
    "path": "src/behaviour/Rotate.js",
    "content": "(function(Proton, undefined) {\n\n    /* The Rotate class is the base\n     * for the other Behaviour\n     *\n     * @class Behaviour * @constructor \n     * @example new Proton.Rotate(Proton.createSpan(-1,1),Proton.createSpan(-1,1),Proton.createSpan(-1,1)); \n     * @example new Proton.Rotate(); \n     * @example new Proton.Rotate(\"random\"); \n     */\n\n    function Rotate(x, y, z, life, easing) {\n        Rotate._super_.call(this, life, easing);\n        this.reset(x, y, z);\n        this.name = \"Rotate\";\n    }\n\n    Proton.Util.inherits(Rotate, Proton.Behaviour);\n    Rotate.prototype.reset = function(a, b, c, life, easing) {\n        this.a = a || 0;\n        this.b = b || 0;\n        this.c = c || 0;\n\n        if (a === undefined || a == \"same\") {\n            this._type = \"same\";\n        } else if (b == undefined) {\n            this._type = \"set\";\n        } else if (c === undefined) {\n            this._type = \"to\";\n        } else {\n            this._type = \"add\";\n            this.a = Proton.createSpan(this.a * Proton.DR);\n            this.b = Proton.createSpan(this.b * Proton.DR);\n            this.c = Proton.createSpan(this.c * Proton.DR);\n        }\n\n        life && Rotate._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Rotate.prototype.initialize = function(particle) {\n        switch (this._type) {\n            case \"same\":\n                break;\n\n            case \"set\":\n                this._setRotation(particle.rotation, this.a);\n                break;\n\n            case \"to\":\n                particle.transform.fR = particle.transform.fR || new Proton.Vector3D;\n                particle.transform.tR = particle.transform.tR || new Proton.Vector3D;\n                this._setRotation(particle.transform.fR, this.a);\n                this._setRotation(particle.transform.tR, this.b);\n                break;\n\n            case \"add\":\n                particle.transform.addR = new Proton.Vector3D(this.a.getValue(), this.b.getValue(), this.c.getValue());\n                break;\n        }\n    };\n\n    Rotate.prototype._setRotation = function(vec3, value) {\n        vec3 = vec3 || new Proton.Vector3D;\n        if (value == \"random\") {\n            var x = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            var y = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            var z = Proton.MathUtils.randomAToB(-Proton.PI, Proton.PI);\n            vec3.set(x, y, z);\n        } else if (value instanceof Proton.Vector3D) {\n            vec3.copy(value);\n        }\n    };\n\n    Rotate.prototype.applyBehaviour = function(particle, time, index) {\n        Rotate._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        switch (this._type) {\n            case \"same\":\n                if (!particle.rotation) particle.rotation = new Proton.Vector3D;\n                particle.rotation.eulerFromDir(particle.v);\n                //http://stackoverflow.com/questions/21622956/how-to-convert-direction-vector-to-euler-angles\n                //console.log(particle.rotation);\n                break;\n\n            case \"set\":\n                //\n                break;\n\n            case \"to\":\n                particle.rotation.x = Proton.MathUtils.lerp(particle.transform.fR.x, particle.transform.tR.x, this.energy);\n                particle.rotation.y = Proton.MathUtils.lerp(particle.transform.fR.y, particle.transform.tR.y, this.energy);\n                particle.rotation.z = Proton.MathUtils.lerp(particle.transform.fR.z, particle.transform.tR.z, this.energy);\n                break;\n\n            case \"add\":\n                particle.rotation.add(particle.transform.addR);\n                break;\n        }\n    };\n\n    Proton.Rotate = Rotate;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Scale.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Scale class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n\n    function Scale(a, b, life, easing) {\n        Scale._super_.call(this, life, easing);\n        this.reset(a, b);\n        this.name = \"Scale\";\n    }\n\n\n    Proton.Util.inherits(Scale, Proton.Behaviour);\n    Scale.prototype.reset = function(a, b, life, easing) {\n        if (b == null || b == undefined)\n            this._same = true;\n        else\n            this._same = false;\n\n        this.a = Proton.createSpan(Proton.Util.initValue(a, 1));\n        this.b = Proton.createSpan(b);\n\n        life && Scale._super_.prototype.reset.call(this, life, easing);\n    }\n\n    Scale.prototype.initialize = function(particle) {\n        particle.transform.scaleA = this.a.getValue();\n        particle.transform.oldRadius = particle.radius;\n        if (this._same)\n            particle.transform.scaleB = particle.transform.scaleA;\n        else\n            particle.transform.scaleB = this.b.getValue();\n\n    };\n\n    Scale.prototype.applyBehaviour = function(particle, time, index) {\n        Scale._super_.prototype.applyBehaviour.call(this, particle, time, index);\n        particle.scale = Proton.MathUtils.lerp(particle.transform.scaleA, particle.transform.scaleB, this.energy);\n\n        if (particle.scale < 0.0005) particle.scale = 0;\n        particle.radius = particle.transform.oldRadius * particle.scale;\n    };\n\n    Proton.Scale = Scale;\n})(Proton);\n"
  },
  {
    "path": "src/behaviour/Spring.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Behaviour class is the base for the other Behaviour\n     *\n     * @class Behaviour\n     * @constructor\n     */\n    function Spring(x, y, z, spring, friction, life, easing) {\n        Spring._super_.call(this, life, easing);\n        Spring.prototype.reset(x, y, z, spring, friction);\n        this.name = \"Spring\";\n    }\n\n    Proton.Util.inherits(Spring, Proton.Behaviour);\n    Spring.prototype.reset = function(x, y, z, spring, friction) {\n        if (!this.pos)\n            this.pos = new Proton.Vector3D(x, y, z);\n        else\n            this.pos.set(x, y, z);\n        this.spring = spring || .1;\n        this.friction = friction || .98;\n    }\n\n    Spring.prototype.applyBehaviour = function(particle, time, index) {\n        Spring._super_.prototype.applyBehaviour.call(this, particle, time, index);\n\n        particle.v.x += (this.pos.x - particle.p.x) * this.spring;\n        particle.v.y += (this.pos.y - particle.p.y) * this.spring;\n        particle.v.z += (this.pos.z - particle.p.z) * this.spring;\n\n    };\n\n\n    Proton.Spring = Spring;\n})(Proton);\n"
  },
  {
    "path": "src/core/Particle.js",
    "content": "(function(Proton, undefined) {\n\n    Particle.ID = 0;\n\n    /**\n     * the Particle class\n     * @param {Number} pObj - the parameters of particle config;\n     * @example \n     * var p = new Proton.Particle({life:3,dead:false});\n     * or\n     * var p = new Proton.Particle({mass:1,radius:100});\n     * @constructor\n     */\n    function Particle(pOBJ) {\n        /**\n         * @property {Number}  id               - The particle's id\n         */\n        this.id = 'particle_' + Particle.ID++;\n        this.name = 'Particle';\n        this.reset(\"init\");\n        Proton.Util.setPrototypeByObj(this, pOBJ);\n    }\n\n    Particle.prototype = {\n        getDirection: function() {\n            return Math.atan2(this.v.x, -this.v.y) * (180 / Proton.PI);\n        },\n\n        /**\n         * @property {Number}  life               - The particle's life\n         * @property {Number}  age               - The particle's age\n         * @property {Number}  energy               - The particle's energy loss\n         * @property {Boolean}  dead               - The particle is dead?\n         * @property {Boolean}  sleep               - The particle is sleep?\n         * @property {Object}  target               - The particle's target\n         * @property {Object}  body               - The particle's body\n         * @property {Number}  mass               - The particle's mass\n         * @property {Number}  radius               - The particle's radius\n         * @property {Number}  alpha               - The particle's alpha\n         * @property {Number}  scale               - The particle's scale\n         * @property {Number}  rotation               - The particle's rotation\n         * @property {String|Number}  color               - The particle's color\n         * @property {Function}  easing               - The particle's easing\n         * @property {Proton.Vector3D}  p               - The particle's position\n         * @property {Proton.Vector3D}  v               - The particle's velocity\n         * @property {Proton.Vector3D}  a               - The particle's acceleration\n         * @property {Array}  behaviours               - The particle's behaviours array\n         * @property {Object}  transform               - The particle's transform collection\n         */\n        reset: function(init) {\n            this.life = Infinity;\n            this.age = 0;\n            //energy loss\n            this.energy = 1;\n            this.dead = false;\n            this.sleep = false;\n            this.body = null;\n            this.parent = null;\n            this.mass = 1;\n            this.radius = 10;\n\n            this.alpha = 1;\n            this.scale = 1;\n\n            this.useColor = false;\n            this.useAlpha = false;\n\n            this.easing = Proton.ease.setEasingByName(Proton.ease.easeLinear);\n\n            if (init) {\n                this.p = new Proton.Vector3D();\n                this.v = new Proton.Vector3D();\n                this.a = new Proton.Vector3D();\n                this.old = {};\n                this.old.p = this.p.clone();\n                this.old.v = this.v.clone();\n                this.old.a = this.a.clone();\n\n                this.behaviours = [];\n                this.transform = {};\n                this.color = { r: 0, g: 0, b: 0 };\n                this.rotation = new Proton.Vector3D;\n            } else {\n                this.p.set(0, 0, 0);\n                this.v.set(0, 0, 0);\n                this.a.set(0, 0, 0);\n                this.old.p.set(0, 0, 0);\n                this.old.v.set(0, 0, 0);\n                this.old.a.set(0, 0, 0);\n\n                this.color.r = 0;\n                this.color.g = 0;\n                this.color.b = 0;\n\n                this.rotation.clear();\n\n                Proton.Util.destroyObject(this.transform);\n                this.removeAllBehaviours();\n            }\n\n            return this;\n        },\n\n        update: function(time, index) {\n            if (!this.sleep) {\n                this.age += time;\n\n                var i = this.behaviours.length;\n                while (i--) {\n                    this.behaviours[i] && this.behaviours[i].applyBehaviour(this, time, index)\n                }\n            } else {\n                //sleep\n            }\n\n            if (this.age >= this.life) {\n                this.destroy();\n            } else {\n                var scale = this.easing(this.age / this.life);\n                this.energy = Math.max(1 - scale, 0);\n            }\n\n        },\n\n        addBehaviour: function(behaviour) {\n            this.behaviours.push(behaviour);\n            behaviour.initialize(this);\n        },\n\n        addBehaviours: function(behaviours) {\n            var i = behaviours.length;\n            while (i--) {\n                this.addBehaviour(behaviours[i]);\n            }\n        },\n\n        removeBehaviour: function(behaviour) {\n            var index = this.behaviours.indexOf(behaviour);\n            if (index > -1) {\n                this.behaviours.splice(index, 1);\n            }\n        },\n\n        removeAllBehaviours: function() {\n            Proton.Util.destroyArray(this.behaviours);\n        },\n\n        /**\n         * Destory this particle\n         * @method destroy\n         */\n        destroy: function() {\n            this.removeAllBehaviours();\n            this.energy = 0;\n            this.dead = true;\n            this.parent = null;\n        }\n    };\n\n    Proton.Particle = Particle;\n})(Proton);\n"
  },
  {
    "path": "src/core/Pool.js",
    "content": "(function(Proton, undefined) {\n\n    function Pool() {\n        this.cID = 0;\n        this.list = {};\n    }\n\n    Pool.prototype = {\n        create: function(obj) {\n            this.cID++;\n\n            if (typeof obj == \"function\")\n                return new obj;\n            else\n                return obj.clone();\n        },\n\n        getCount: function() {\n            var count = 0;\n            for (var id in this.list)\n                count += this.list[id].length;\n\n            return count++;;\n        },\n\n        get: function(obj) {\n            var p, puid = obj.__puid || Proton.PUID.id(obj);\n            if (this.list[puid] && this.list[puid].length > 0)\n                p = this.list[puid].pop();\n            else\n                p = this.create(obj);\n\n            p.__puid = obj.__puid || puid;\n            return p;\n        },\n\n        expire: function(obj) {\n            return this._getList(obj.__puid).push(obj);\n        },\n\n        destroy: function() {\n            for (var id in this.list) {\n                this.list[id].length = 0;\n                delete this.list[id];\n            }\n        },\n\n        _getList: function(uid) {\n            uid = uid || \"default\";\n            if (!this.list[uid]) this.list[uid] = [];\n            return this.list[uid];\n        }\n    }\n\n    Proton.Pool = Pool;\n\n})(Proton);\n"
  },
  {
    "path": "src/core/Proton.js",
    "content": "(function(window, undefined) {\n    //the max particle number in pool\n    Proton.POOL_MAX = 500;\n    Proton.TIME_STEP = 60;\n    Proton.PI = 3.142;\n    Proton.DR = Proton.PI / 180;\n\n    //1:100\n    Proton.MEASURE = 100;\n    Proton.EULER = 'euler';\n    Proton.RK2 = 'runge-kutta2';\n    Proton.RK4 = 'runge-kutta4';\n    Proton.VERLET = 'verlet';\n\n    Proton.PARTICLE_CREATED = 'partilcleCreated';\n    Proton.PARTICLE_UPDATE = 'partilcleUpdate';\n    Proton.PARTICLE_SLEEP = 'particleSleep';\n    Proton.PARTICLE_DEAD = 'partilcleDead';\n    Proton.PROTON_UPDATE = 'protonUpdate';\n    Proton.PROTON_UPDATE_AFTER = 'protonUpdateAfter';\n    Proton.EMITTER_ADDED = 'emitterAdded';\n    Proton.EMITTER_REMOVED = 'emitterRemoved';\n\n    Proton.bindEmtterEvent = false;\n\n    /**\n     * @name Proton is a particle engine for three.js\n     *\n     * @class Proton\n     * @param {number} preParticles input any number\n     * @param {number} integrationType input any number\n     * @example var proton = new Proton(200);\n     */\n\n    function Proton(preParticles, integrationType) {\n        this.preParticles = Proton.Util.initValue(preParticles, Proton.POOL_MAX);\n        this.integrationType = Proton.Util.initValue(integrationType, Proton.EULER);\n\n        this.emitters = [];\n        this.renderers = [];\n\n        this.pool = new Proton.Pool();\n        Proton.integrator = new Proton.Integration(this.integrationType);\n    }\n\n\n    Proton.prototype = {\n        /**\n         * @name add a type of Renderer\n         *\n         * @method addRender\n         * @param {Renderer} render\n         */\n        addRender: function(renderer) {\n            this.renderers.push(renderer);\n            renderer.init(this);\n        },\n\n        /**\n         * @name add a type of Renderer\n         *\n         * @method addRender\n         * @param {Renderer} render\n         */\n        removeRender: function(renderer) {\n            this.renderers.splice(this.renderers.indexOf(renderer), 1);\n            renderer.remove(this);\n        },\n\n        /**\n         * add the Emitter\n         *\n         * @method addEmitter\n         * @param {Emitter} emitter\n         */\n        addEmitter: function(emitter) {\n            this.emitters.push(emitter);\n            emitter.parent = this;\n            this.dispatchEvent(\"EMITTER_ADDED\", emitter);\n        },\n\n        removeEmitter: function(emitter) {\n            if (emitter.parent != this) return;\n\n            this.emitters.splice(this.emitters.indexOf(emitter), 1);\n            emitter.parent = null;\n            this.dispatchEvent(\"EMITTER_REMOVED\", emitter);\n        },\n\n        update: function($delta) {\n            this.dispatchEvent(\"PROTON_UPDATE\", this);\n\n            var delta = $delta || 0.0167;\n            if (delta > 0) {\n                var i = this.emitters.length;\n                while (i--) this.emitters[i].update(delta);\n            }\n\n            this.dispatchEvent(\"PROTON_UPDATE_AFTER\", this);\n        },\n\n        /**\n         * getCount\n         * @name get the count of particle\n         * @return (number) particles count\n         */\n        getCount: function() {\n            var total = 0;\n            var i, length = this.emitters.length;\n            for (i = 0; i < length; i++) total += this.emitters[i].particles.length;\n            return total;\n        },\n\n        /**\n         * destroy\n         * @name destroy the proton\n         */\n        destroy: function() {\n            var i = 0,\n                length = this.emitters.length;\n\n            for (i; i < length; i++) {\n                this.emitters[i].destroy();\n                delete this.emitters[i];\n            }\n\n            this.emitters.length = 0;\n            this.pool.destroy();\n        }\n    };\n\n    window.Proton = Proton;\n})(window);\n"
  },
  {
    "path": "src/debug/Debug.js",
    "content": "(function(Proton, undefined) {\n    var Debug = Debug || {\n        addEventListener: function(proton, fun) {\n            proton.addEventListener(\"PROTON_UPDATE\", function(e) {\n                fun(e);\n            });\n        },\n\n        drawZone: function(proton, container, zone) {\n            var geometry, material, mesh;\n\n            if (zone instanceof Proton.PointZone) {\n                geometry = new THREE.SphereGeometry(15);\n            } else if (zone instanceof Proton.LineZone) {\n\n            } else if (zone instanceof Proton.BoxZone) {\n                geometry = new THREE.BoxGeometry(zone.width, zone.height, zone.depth);\n            } else if (zone instanceof Proton.SphereZone) {\n                geometry = new THREE.SphereGeometry(zone.radius, 10, 10);\n            } else if (zone instanceof Proton.MeshZone) {\n                if (zone.geometry instanceof THREE.Geometry)\n                    geometry = zone.geometry;\n                else\n                    geometry = zone.geometry.geometry;\n\n                geometry = new THREE.SphereGeometry(zone.radius, 10, 10);\n            }\n\n            material = new THREE.MeshBasicMaterial({ color: \"#2194ce\", wireframe: true });\n            mesh = new THREE.Mesh(geometry, material);\n            container.add(mesh);\n\n            this.addEventListener(proton, function(e) {\n                mesh.position.set(zone.x, zone.y, zone.z);\n            });\n        },\n\n        drawEmitter: function(proton, container, emitter, color) {\n            var geometry = new THREE.OctahedronGeometry(15);\n            var material = new THREE.MeshBasicMaterial({ color: color || \"#aaa\", wireframe: true });\n            var mesh = new THREE.Mesh(geometry, material);\n            container.add(mesh);\n\n            this.addEventListener(proton, function() {\n                mesh.position.copy(emitter.p);\n                mesh.rotation.set(emitter.rotation.x, emitter.rotation.y, emitter.rotation.z);\n            });\n        },\n\n        renderInfo: function() {\n            function getCreatedNumber(proton, type) {\n                var pool = type == \"material\" ? \"_materialPool\" : \"_targetPool\";\n                var renderer = proton.renderers[0];\n                return renderer[pool].cID;\n            }\n\n            function getEmitterPos(proton) {\n                var e = proton.emitters[0];\n                return Math.round(e.p.x) + \",\" + Math.round(e.p.y) + \",\" + Math.round(e.p.z);\n            }\n\n            return function(proton, style) {\n                this.addInfo(style);\n                var str = \"\";\n                switch (this._infoType) {\n                    case 2:\n                        str += \"emitter:\" + proton.emitters.length + \"<br>\";\n                        str += \"em speed:\" + proton.emitters[0].cID + \"<br>\";\n                        str += \"pos:\" + getEmitterPos(proton);\n                        break;\n\n                    case 3:\n                        str += proton.renderers[0].name + \"<br>\";\n                        str += \"target:\" + getCreatedNumber(proton, \"target\") + \"<br>\";\n                        str += \"material:\" + getCreatedNumber(proton, \"material\");\n                        break;\n\n                    default:\n                        str += \"particles:\" + proton.getCount() + \"<br>\";\n                        str += \"pool:\" + proton.pool.getCount() + \"<br>\";\n                        str += \"total:\" + (proton.getCount() + proton.pool.getCount());\n                }\n                this._infoCon.innerHTML = str;\n            }\n        }(),\n\n        addInfo: function() {\n            return function(style) {\n                var self = this;\n                if (!this._infoCon) {\n                    this._infoCon = document.createElement('div');\n                    this._infoCon.style.cssText = [\n                        'position:fixed;bottom:0px;left:0;cursor:pointer;',\n                        'opacity:0.9;z-index:10000;padding:10px;font-size:12px;',\n                        'width:120px;height:50px;background-color:#002;color:#0ff;'\n                    ].join('');\n\n                    this._infoType = 1;\n                    this._infoCon.addEventListener('click', function(event) {\n                        self._infoType++;\n                        if (self._infoType > 3) self._infoType = 1;\n                    }, false);\n\n                    var bg, color;\n                    switch (style) {\n                        case 2:\n                            bg = \"#201\";\n                            color = \"#f08\";\n                            break;\n\n                        case 3:\n                            bg = \"#020\";\n                            color = \"#0f0\";\n                            break;\n\n                        default:\n                            bg = \"#002\";\n                            color = \"#0ff\";\n                    }\n\n                    this._infoCon.style[\"background-color\"] = bg;\n                    this._infoCon.style[\"color\"] = color;\n                }\n\n                if (!this._infoCon.parentNode) document.body.appendChild(this._infoCon);\n            }\n        }()\n    }\n\n    Proton.Debug = Debug;\n})(Proton);\n"
  },
  {
    "path": "src/debug/log.js",
    "content": "/**\n * You can use this emit particles.\n *\n * This method will console.log the fixed number of your info  in updata or requestAnimationFrame\n * \n * use like this Proton.log('+12',mc); log 12 times\n *\n * @class Proton.log\n * @constructor\n * @param {*} logInfo;\n */\n(function(Proton, undefined) {\n    var log = function() {\n        if (window.console && window.console.trace) {\n            var arg = Array.prototype.slice.call(arguments);\n            var s1 = arguments[0] + \"\";\n            if (s1.indexOf('+') == 0) {\n                var n = parseInt(arguments[0]);\n                if (log.once < n) {\n                    arg.shift();\n                    console.trace.apply(console, arg);\n                    log.once++;\n                }\n            } else {\n                arg.unshift(\"+15\");\n                log.apply(console, arg);\n            }\n        }\n    }\n\n    log.once = 0;\n    Proton.log = log;\n})(Proton);\n"
  },
  {
    "path": "src/ease/ease.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The Ease class provides a collection of easing functions for use with Proton\n     */\n    var ease = ease || {\n        easeLinear: function(value) {\n            return value;\n        },\n\n        easeInQuad: function(value) {\n            return Math.pow(value, 2);\n        },\n\n        easeOutQuad: function(value) {\n            return -(Math.pow((value - 1), 2) - 1);\n        },\n\n        easeInOutQuad: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 2);\n            return -0.5 * ((value -= 2) * value - 2);\n        },\n\n        easeInCubic: function(value) {\n            return Math.pow(value, 3);\n        },\n\n        easeOutCubic: function(value) {\n            return (Math.pow((value - 1), 3) + 1);\n        },\n\n        easeInOutCubic: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 3);\n            return 0.5 * (Math.pow((value - 2), 3) + 2);\n        },\n\n        easeInQuart: function(value) {\n            return Math.pow(value, 4);\n        },\n\n        easeOutQuart: function(value) {\n            return -(Math.pow((value - 1), 4) - 1);\n        },\n\n        easeInOutQuart: function(value) {\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(value, 4);\n            return -0.5 * ((value -= 2) * Math.pow(value, 3) - 2);\n        },\n\n        easeInSine: function(value) {\n            return -Math.cos(value * (Proton.PI / 2)) + 1;\n        },\n\n        easeOutSine: function(value) {\n            return Math.sin(value * (Proton.PI / 2));\n        },\n\n        easeInOutSine: function(value) {\n            return (-0.5 * (Math.cos(Proton.PI * value) - 1));\n        },\n\n        easeInExpo: function(value) {\n            return (value === 0) ? 0 : Math.pow(2, 10 * (value - 1));\n        },\n\n        easeOutExpo: function(value) {\n            return (value === 1) ? 1 : -Math.pow(2, -10 * value) + 1;\n        },\n\n        easeInOutExpo: function(value) {\n            if (value === 0)\n                return 0;\n            if (value === 1)\n                return 1;\n            if ((value /= 0.5) < 1)\n                return 0.5 * Math.pow(2, 10 * (value - 1));\n            return 0.5 * (-Math.pow(2, -10 * --value) + 2);\n        },\n\n        easeInCirc: function(value) {\n            return -(Math.sqrt(1 - (value * value)) - 1);\n        },\n\n        easeOutCirc: function(value) {\n            return Math.sqrt(1 - Math.pow((value - 1), 2));\n        },\n\n        easeInOutCirc: function(value) {\n            if ((value /= 0.5) < 1)\n                return -0.5 * (Math.sqrt(1 - value * value) - 1);\n            return 0.5 * (Math.sqrt(1 - (value -= 2) * value) + 1);\n        },\n\n        easeInBack: function(value) {\n            var s = 1.70158;\n            return (value) * value * ((s + 1) * value - s);\n        },\n\n        easeOutBack: function(value) {\n            var s = 1.70158;\n            return (value = value - 1) * value * ((s + 1) * value + s) + 1;\n        },\n\n        easeInOutBack: function(value) {\n            var s = 1.70158;\n            if ((value /= 0.5) < 1)\n                return 0.5 * (value * value * (((s *= (1.525)) + 1) * value - s));\n            return 0.5 * ((value -= 2) * value * (((s *= (1.525)) + 1) * value + s) + 2);\n        },\n\n        setEasingByName: function(easeName) {\n            if (!!ease[easeName])\n                return ease[easeName];\n            else\n                return ease.easeLinear;\n        }\n    }\n\n\n    for (var id in ease) {\n        if (id != \"setEasingByName\") Proton[id] = ease[id];\n    }\n\n    Proton.ease = ease;\n\n})(Proton);\n"
  },
  {
    "path": "src/emitter/BehaviourEmitter.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The BehaviourEmitter class inherits from Proton.Emitter\n     *\n     * use the BehaviourEmitter you can add behaviours to self;\n     * @class Proton.BehaviourEmitter\n     * @constructor\n     * @param {Object} pObj the parameters object;\n     */\n    function BehaviourEmitter(pObj) {\n        this.selfBehaviours = [];\n        BehaviourEmitter._super_.call(this, pObj);\n    };\n\n    Proton.Util.inherits(BehaviourEmitter, Proton.Emitter);\n    /**\n     * add the Behaviour to emitter;\n     *\n     * you can use Behaviours array:emitter.addSelfBehaviour(Behaviour1,Behaviour2,Behaviour3);\n     * @method addSelfBehaviour\n     * @param {Proton.Behaviour} behaviour like this new Proton.Color('random')\n     */\n    BehaviourEmitter.prototype.addSelfBehaviour = function() {\n        var length = arguments.length,\n            i;\n        for (i = 0; i < length; i++) {\n            this.selfBehaviours.push(arguments[i]);\n        }\n    };\n    /**\n     * remove the Behaviour for self\n     * @method removeSelfBehaviour\n     * @param {Proton.Behaviour} behaviour a behaviour\n     */\n    BehaviourEmitter.prototype.removeSelfBehaviour = function(behaviour) {\n        var index = this.selfBehaviours.indexOf(behaviour);\n        if (index > -1) this.selfBehaviours.splice(index, 1);\n    };\n\n    BehaviourEmitter.prototype.update = function(time) {\n        BehaviourEmitter._super_.prototype.update.call(this, time);\n\n        if (!this.sleep) {\n            var length = this.selfBehaviours.length,\n                i;\n            for (i = 0; i < length; i++) {\n                this.selfBehaviours[i].applyBehaviour(this, time, i)\n            }\n        }\n    }\n\n    Proton.BehaviourEmitter = BehaviourEmitter;\n})(Proton);\n"
  },
  {
    "path": "src/emitter/Emitter.js",
    "content": "(function(Proton, undefined) {\n    function Emitter(pObj) {\n        this.initializes = [];\n        this.particles = [];\n        this.behaviours = [];\n        this.currentEmitTime = 0;\n        this.totalEmitTimes = -1;\n\n        /**\n         * @property {Number} damping -The friction coefficient for all particle emit by This;\n         * @default 0.006\n         */\n        this.damping = .006;\n        /**\n         * If bindEmitter the particles can bind this emitter's property;\n         * @property bindEmitter\n         * @type {Boolean}\n         * @default true\n         */\n        this.bindEmitter = true;\n        /**\n         * The number of particles per second emit (a [particle]/b [s]);\n         * @property rate\n         * @type {Rate}\n         * @default Rate(1, .1)\n         */\n        this.rate = new Proton.Rate(1, .1);\n        Emitter._super_.call(this, pObj);\n        /**\n         * The emitter's id;\n         * @property id\n         * @type {String} id\n         */\n        this.id = 'emitter_' + Emitter.ID++;\n        this.cID = 0;\n        this.name = 'Emitter';\n    };\n    Emitter.ID = 0;\n\n    Proton.Util.inherits(Emitter, Proton.Particle);\n    Proton.EventDispatcher.initialize(Emitter.prototype);\n\n    /**\n     * start emit particle\n     * @method emit\n     * @param {Number} totalEmitTimes total emit times;\n     * @param {String} life the life of this emitter\n     */\n    Emitter.prototype.emit = function(totalEmitTimes, life) {\n        this.currentEmitTime = 0;\n        this.totalEmitTimes = Proton.Util.initValue(totalEmitTimes, Infinity);\n\n        if (life == true || life == 'life' || life == 'destroy') {\n            this.life = totalEmitTimes == 'once' ? 1 : this.totalEmitTimes;\n        } else if (!isNaN(life)) {\n            this.life = life;\n        }\n\n        this.rate.init();\n    };\n\n    /**\n     * stop emiting\n     * @method stopEmit\n     */\n    Emitter.prototype.stopEmit = function() {\n        this.totalEmitTimes = -1;\n        this.currentEmitTime = 0;\n    };\n\n    /**\n     * remove current all particles\n     * @method removeAllParticles\n     */\n    Emitter.prototype.removeAllParticles = function() {\n        var i = this.particles.length;\n        while (i--) this.particles[i].dead = true;\n    };\n\n    /**\n     * create single particle;\n     * \n     * can use emit({x:10},new Gravity(10),{'particleUpdate',fun}) or emit([{x:10},new Initialize],new Gravity(10),{'particleUpdate',fun})\n     * @method removeAllParticles\n     */\n    Emitter.prototype.createParticle = function(initialize, behaviour) {\n        var particle = this.parent.pool.get(Proton.Particle);\n        this.setupParticle(particle, initialize, behaviour);\n        this.parent && this.parent.dispatchEvent(\"PARTICLE_CREATED\", particle);\n        Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_CREATED\", particle);\n\n        return particle;\n    };\n    /**\n     * add initialize to this emitter\n     * @method addSelfInitialize\n     */\n    Emitter.prototype.addSelfInitialize = function(pObj) {\n        if (pObj['init']) {\n            pObj.init(this);\n        } else {\n            this.initAll();\n        }\n    };\n\n\n    /**\n     * add the Initialize to particles;\n     * \n     * you can use initializes array:for example emitter.addInitialize(initialize1,initialize2,initialize3);\n     * @method addInitialize\n     * @param {Initialize} initialize like this new Radius(1, 12)\n     */\n    Emitter.prototype.addInitialize = function() {\n        var i = arguments.length;\n        while (i--) this.initializes.push(arguments[i]);\n    };\n\n\n    /**\n     * remove the Initialize\n     * @method removeInitialize\n     * @param {Initialize} initialize a initialize\n     */\n    Emitter.prototype.removeInitialize = function(initializer) {\n        var index = this.initializes.indexOf(initializer);\n        if (index > -1) this.initializes.splice(index, 1);\n    };\n\n    /**\n     * remove all Initializes\n     * @method removeInitializers\n     */\n    Emitter.prototype.removeInitializers = function() {\n        Proton.Util.destroyArray(this.initializes);\n    };\n    /**\n     * add the Behaviour to particles;\n     * \n     * you can use Behaviours array:emitter.addBehaviour(Behaviour1,Behaviour2,Behaviour3);\n     * @method addBehaviour\n     * @param {Behaviour} behaviour like this new Color('random')\n     */\n    Emitter.prototype.addBehaviour = function() {\n        var i = arguments.length;\n        while (i--) this.behaviours.push(arguments[i]);\n    };\n    /**\n     * remove the Behaviour\n     * @method removeBehaviour\n     * @param {Behaviour} behaviour a behaviour\n     */\n    Emitter.prototype.removeBehaviour = function(behaviour) {\n        var index = this.behaviours.indexOf(behaviour);\n        if (index > -1) this.behaviours.splice(index, 1);\n    };\n    /**\n     * remove all behaviours\n     * @method removeAllBehaviours\n     */\n    Emitter.prototype.removeAllBehaviours = function() {\n        Proton.Util.destroyArray(this.behaviours);\n    };\n\n    Emitter.prototype.integrate = function(time) {\n        var damping = 1 - this.damping;\n        Proton.integrator.integrate(this, time, damping);\n\n        var i = this.particles.length;\n        while (i--) {\n            var particle = this.particles[i];\n            particle.update(time, i);\n            Proton.integrator.integrate(particle, time, damping);\n\n            this.parent && this.parent.dispatchEvent(\"PARTICLE_UPDATE\", particle);\n            Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_UPDATE\", particle);\n        }\n    };\n\n    Emitter.prototype.emitting = function(time) {\n        if (this.totalEmitTimes == 'once') {\n            var i = this.rate.getValue(99999);\n            if (i > 0) this.cID = i;\n            while (i--) this.createParticle();\n            this.totalEmitTimes = 'none';\n\n        } else if (!isNaN(this.totalEmitTimes)) {\n            this.currentEmitTime += time;\n            if (this.currentEmitTime < this.totalEmitTimes) {\n                var i = this.rate.getValue(time);\n                if (i > 0) this.cID = i;\n                while (i--) this.createParticle();\n            }\n        }\n    }\n\n    Emitter.prototype.update = function(time) {\n        this.age += time;\n        if (this.dead || this.age >= this.life) {\n            this.destroy();\n        }\n\n        this.emitting(time);\n        this.integrate(time);\n\n        var particle, i = this.particles.length;\n        while (i--) {\n            particle = this.particles[i];\n            if (particle.dead) {\n                this.parent && this.parent.dispatchEvent(\"PARTICLE_DEAD\", particle);\n                Proton.bindEmtterEvent && this.dispatchEvent(\"PARTICLE_DEAD\", particle);\n\n                this.parent.pool.expire(particle.reset());\n                this.particles.splice(i, 1);\n            }\n        }\n    };\n\n    Emitter.prototype.setupParticle = function(particle, initialize, behaviour) {\n        var initializes = this.initializes;\n        var behaviours = this.behaviours;\n\n        if (initialize) {\n            if (Proton.Util.isArray(initialize))\n                initializes = initialize;\n            else\n                initializes = [initialize];\n        }\n\n        if (behaviour) {\n            if (Proton.Util.isArray(behaviour))\n                behaviours = behaviour;\n            else\n                behaviours = [behaviour];\n        }\n\n        Proton.InitializeUtil.initialize(this, particle, initializes);\n        particle.addBehaviours(behaviours);\n        particle.parent = this;\n        this.particles.push(particle);\n    };\n\n    /**\n     * Destory this Emitter\n     * @method destroy\n     */\n    Emitter.prototype.destroy = function() {\n        this.dead = true;\n        this.energy = 0;\n        this.totalEmitTimes = -1;\n\n        if (this.particles.length == 0) {\n            this.removeInitializers();\n            this.removeAllBehaviours();\n\n            this.parent && this.parent.removeEmitter(this);\n        }\n    }\n\n\n    Proton.Emitter = Emitter;\n})(Proton);\n"
  },
  {
    "path": "src/emitter/FollowEmitter.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The FollowEmitter class inherits from Proton.Emitter\n     *\n     * use the FollowEmitter will emit particle when mousemoving\n     *\n     * @class Proton.FollowEmitter\n     * @constructor\n     * @param {Element} mouseTarget mouseevent's target;\n     * @param {Number} ease the easing of following speed;\n     * @default 0.7\n     * @param {Object} pObj the parameters object;\n     */\n    function FollowEmitter(mouseTarget, ease, pObj) {\n        this.mouseTarget = Proton.Util.initValue(mouseTarget, window);\n        this.ease = Proton.Util.initValue(ease, .7);\n        this._allowEmitting = false;\n        this.mouse = new Proton.Vector3D();\n        this.initEventHandler();\n\n        FollowEmitter._super_.call(this, pObj);\n    };\n\n    Proton.Util.inherits(FollowEmitter, Proton.Emitter);\n    FollowEmitter.prototype.initEventHandler = function() {\n        var self = this;\n        this.mousemoveHandler = function(e) {\n            self.mousemove.call(self, e);\n        };\n\n        this.mousedownHandler = function(e) {\n            self.mousedown.call(self, e);\n        };\n\n        this.mouseupHandler = function(e) {\n            self.mouseup.call(self, e);\n        };\n        \n        this.mouseTarget.addEventListener('mousemove', this.mousemoveHandler, false);\n    }\n\n    /**\n     * start emit particle\n     * @method emit\n     */\n    FollowEmitter.prototype.emit = function() {\n        this._allowEmitting = true;\n    }\n\n    /**\n     * stop emiting\n     * @method stopEmit\n     */\n    FollowEmitter.prototype.stopEmit = function() {\n        this._allowEmitting = false;\n    }\n\n    FollowEmitter.prototype.setCameraAndCanvas = function(camera, canvas) {\n        this.camera = camera;\n        this.canvas = canvas;\n    }\n\n    FollowEmitter.prototype.setCameraAndRenderer = function(camera, renderer) {\n        this.camera = camera;\n        this.renderer = renderer;\n        this.canvas = renderer.domElement;\n    }\n\n    FollowEmitter.prototype.mousemove = function(e) {\n        var rect = this.canvas.getBoundingClientRect();\n        var x = e.clientX - rect.left;\n        var y = e.clientY - rect.top;\n        var ratio = this.renderer? this.renderer.getPixelRatio() : 1;\n        x *= ratio;\n        y *= ratio;\n\n        this.mouse.x += (x - this.mouse.x) * this.ease;\n        this.mouse.y += (y - this.mouse.y) * this.ease;\n        \n        this.p.copy(Proton.THREEUtil.toSpacePos(this.mouse, this.camera, this.canvas, this.renderer));\n\n        if (this._allowEmitting){\n            FollowEmitter._super_.prototype.emit.call(this, 'once');\n        }\n    };\n\n    /**\n     * Destory this Emitter\n     * @method destroy\n     */\n    FollowEmitter.prototype.destroy = function() {\n        FollowEmitter._super_.prototype.destroy.call(this);\n        this.mouseTarget.removeEventListener('mousemove', this.mousemoveHandler, false);\n    }\n\n    Proton.FollowEmitter = FollowEmitter;\n})(Proton);\n"
  },
  {
    "path": "src/events/EventDispatcher.js",
    "content": "/*\n * EventDispatcher\n * Visit http://createjs.com/ for documentation, updates and examples.\n *\n **/\n\n(function(Proton, undefined) {\n    function EventDispatcher() {\n        this.initialize();\n    };\n\n    EventDispatcher.initialize = function(target) {\n        target.addEventListener = p.addEventListener;\n        target.removeEventListener = p.removeEventListener;\n        target.removeAllEventListeners = p.removeAllEventListeners;\n        target.hasEventListener = p.hasEventListener;\n        target.dispatchEvent = p.dispatchEvent;\n    };\n\n    var p = EventDispatcher.prototype;\n\n    p._listeners = null;\n\n    p.initialize = function() {};\n    p.addEventListener = function(type, listener) {\n        if (!this._listeners) {\n            this._listeners = {};\n        } else {\n            this.removeEventListener(type, listener);\n        }\n\n        if (!this._listeners[type]) this._listeners[type] = []\n        this._listeners[type].push(listener);\n\n        return listener;\n    };\n\n    p.removeEventListener = function(type, listener) {\n        if (!this._listeners) return;\n        if (!this._listeners[type]) return;\n\n        var arr = this._listeners[type];\n        for (var i = 0, l = arr.length; i < l; i++) {\n            if (arr[i] == listener) {\n                if (l == 1) {\n                    delete(this._listeners[type]);\n                }\n                // allows for faster checks.\n                else {\n                    arr.splice(i, 1);\n                }\n                break;\n            }\n        }\n    };\n\n    p.removeAllEventListeners = function(type) {\n        if (!type)\n            this._listeners = null;\n        else if (this._listeners)\n            delete(this._listeners[type]);\n    };\n\n    p.dispatchEvent = function(eventName, eventTarget) {\n        var ret = false,\n            listeners = this._listeners;\n\n        if (eventName && listeners) {\n            var arr = listeners[eventName];\n            if (!arr) return ret;\n\n            arr = arr.slice();\n            // to avoid issues with items being removed or added during the dispatch\n\n            var handler, i = arr.length;\n            while (i--) {\n                var handler = arr[i];\n                ret = ret || handler(eventTarget);\n            }\n            \n        }\n\n        return !!ret;\n    };\n\n    p.hasEventListener = function(type) {\n        var listeners = this._listeners;\n        return !!(listeners && listeners[type]);\n    };\n\n    EventDispatcher.initialize(Proton.prototype);\n    Proton.EventDispatcher = EventDispatcher;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Body.js",
    "content": "(function(Proton, undefined) {\n    function Body(body, w, h) {\n        Body._super_.call(this);\n        this.body = Proton.createArraySpan(body);\n        this.w = w;\n        this.h = Proton.Util.initValue(h, this.w);\n    }\n\n    Proton.Util.inherits(Body, Proton.Initialize);\n\n    Body.prototype.initialize = function(particle) {\n        var body = this.body.getValue();\n        if (!!this.w) {\n            particle.body = {\n                width: this.w,\n                height: this.h,\n                body: body\n            };\n        } else {\n            particle.body = body;\n        }\n    };\n\n    Proton.Body = Body;\n})(Proton);\n\n"
  },
  {
    "path": "src/initialize/Initialize.js",
    "content": "(function(Proton, undefined) {\n    function Initialize() {\n        this.name = \"Initialize\";\n    }\n\n\n    Initialize.prototype.reset = function() {\n\n    }\n\n    Initialize.prototype.init = function(emitter, particle) {\n        if (particle) {\n            this.initialize(particle);\n        } else {\n            this.initialize(emitter);\n        }\n    };\n\n    ///sub class init\n    Initialize.prototype.initialize = function(target) {};\n    Proton.Initialize = Initialize;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/InitializeUtil.js",
    "content": "(function(Proton, undefined) {\n    var InitializeUtil = {\n\n        initialize: function(emitter, particle, initializes) {\n            var i = initializes.length;\n            while (i--) {\n                var initialize = initializes[i];\n                if (initialize instanceof Proton.Initialize)\n                    initialize.init(emitter, particle);\n                else\n                    InitializeUtil.init(emitter, particle, initialize);\n            }\n\n            InitializeUtil.bindEmitter(emitter, particle);\n        },\n\n        //////////////////////init//////////////////////\n        init: function(emitter, particle, initialize) {\n            Proton.Util.setPrototypeByObj(particle, initialize);\n            Proton.Util.setVectorByObj(particle, initialize);\n        },\n\n        bindEmitter: function(emitter, particle) {\n            if (emitter.bindEmitter) {\n                particle.p.add(emitter.p);\n                particle.v.add(emitter.v);\n                particle.a.add(emitter.a);\n                particle.v.applyEuler(emitter.rotation);\n            }\n        }\n    }\n\n    Proton.InitializeUtil = InitializeUtil;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Life.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Life is init particle's Life\n     * @param {Number} a - the Life's start point\n     * @param {Number} b - the Life's end point  \n     * @param {String} c - span's center \n     * @example \n     * var life = new Proton.Life(3,5);\n     * or\n     * var life = new Proton.Life(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Life(a, b, c) {\n        Life._super_.call(this);\n        this.lifePan = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Life, Proton.Initialize);\n    Life.prototype.initialize = function(target) {\n        if (this.lifePan.a == Infinity || this.lifePan.a == \"infi\")\n            target.life = Infinity;\n        else\n            target.life = this.lifePan.getValue();\n    };\n\n\n    Proton.Life = Life;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Mass.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Mass is init particle's Mass\n     * @param {Number} a - the Mass's start point\n     * @param {Number} b - the Mass's end point  \n     * @param {String} c - span's center \n     * @example \n     * var Mass = new Proton.Mass(3,5);\n     * or\n     * var Mass = new Proton.Mass(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Mass(a, b, c) {\n        Mass._super_.call(this);\n        this.massPan = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Mass, Proton.Initialize);\n    Mass.prototype.initialize = function(target) {\n        target.mass = this.massPan.getValue();\n    };\n\n    Proton.Mass = Mass;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Position.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Position is init particle's Position\n     * @param {Zone} zone - the Position zone\n     * @example \n     * var Position = new Proton.Position(new Proton.PointZone(30,100,0));\n     * or\n     * var Position = new Proton.Position(Infinity);\n     * @extends {Proton.Initialize}\n     * @constructor\n     */\n    function Position() {\n        Position._super_.call(this);\n        this.reset.apply(this, arguments);\n    }\n\n\n    Proton.Util.inherits(Position, Proton.Initialize);\n    Position.prototype.reset = function() {\n        if (!this.zones) this.zones = [];\n        else this.zones.length = 0;\n\n        var args = Array.prototype.slice.call(arguments);\n        this.zones = this.zones.concat(args);\n    };\n\n    Position.prototype.addZone = function() {\n        var args = Array.prototype.slice.call(arguments);\n        this.zones = this.zones.concat(args);\n    };\n\n    Position.prototype.initialize = function() {\n        var zone;\n        return function(target) {\n            var zone = this.zones[(Math.random() * this.zones.length) >> 0];\n            zone.getPosition();\n\n            target.p.x = zone.vector.x;\n            target.p.y = zone.vector.y;\n            target.p.z = zone.vector.z;\n        }\n    }();\n\n\n    Proton.Position = Position;\n    Proton.P = Position;\n\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Radius.js",
    "content": "(function(Proton, undefined) {\n\n    /**\n     * Radius is init particle's Radius\n     * @param {Number} a - the Radius's start point\n     * @param {Number} b - the Radius's end point  \n     * @param {String} c - span's center \n     * @example \n     * var Radius = new Proton.Radius(3,5);\n     * or\n     * var Radius = new Proton.Radius(3,1,\"center\");\n     * @extends {Initialize}\n     * @constructor\n     */\n    function Radius(a, b, c) {\n        Radius._super_.call(this);\n        this.radius = Proton.createSpan(a, b, c);\n    }\n\n\n    Proton.Util.inherits(Radius, Proton.Initialize);\n    Radius.prototype.reset = function(a, b, c) {\n        this.radius = Proton.createSpan(a, b, c);\n    };\n\n    Radius.prototype.initialize = function(particle) {\n        particle.radius = this.radius.getValue();\n        particle.transform.oldRadius = particle.radius;\n    };\n\n    Proton.Radius = Radius;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Rate.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * The number of particles per second emission (a [particle]/b [s]);\n     * @class Proton.Rate\n     * @constructor\n     * @param {Array or Number or Proton.Span} numPan the number of each emission;\n     * @param {Array or Number or Proton.Span} timePan the time of each emission;\n     * for example: new Proton.Rate(new Proton.Span(10, 20), new Proton.Span(.1, .25));\n     */\n     \n    function Rate(numPan, timePan) {\n        this.numPan = Proton.createSpan(Proton.Util.initValue(numPan, 1));\n        this.timePan = Proton.createSpan(Proton.Util.initValue(timePan, 1));\n\n        this.startTime = 0;\n        this.nextTime = 0;\n        this.init();\n    }\n\n    Rate.prototype = {\n        init: function() {\n            this.startTime = 0;\n            this.nextTime = this.timePan.getValue();\n        },\n\n        getValue: function(time) {\n            this.startTime += time;\n\n            if (this.startTime >= this.nextTime) {\n                this.init();\n\n                if (this.numPan.b == 1) {\n                    if (this.numPan.getValue(\"Float\") > 0.5)\n                        return 1;\n                    else\n                        return 0;\n                } else {\n                    return this.numPan.getValue(\"Int\");\n                }\n            }\n\n            return 0;\n        }\n    }\n\n    Proton.Rate = Rate;\n})(Proton);\n"
  },
  {
    "path": "src/initialize/Velocity.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Velocity is init particle's Velocity\n     * @param {Number} a - the Life's start point\n     * @param {Number} b - the Life's end point  \n     * @param {String} c - span's center \n     * @example \n     * var life = new Proton.Life(3,5);\n     * or\n     * var life = new Proton.Life(Infinity);\n     * @extends {Initialize}\n     * @constructor\n     */\n    //radius and tha\n    function Velocity(a, b, c) {\n        Velocity._super_.call(this);\n        this.reset(a, b, c);\n        this.dirVec = new Proton.Vector3D(0, 0, 0);\n\n        this.name = \"Velocity\";\n    }\n\n    Proton.Util.inherits(Velocity, Proton.Initialize);\n\n    Velocity.prototype.reset = function(a, b, c) {\n        //[vector,tha]\n        if (a instanceof Proton.Vector3D) {\n            this.radiusPan = Proton.createSpan(1);\n            this.dir = a.clone();\n            this.tha = b * Proton.DR;\n            this._useV = true;\n        }\n\n        //[polar,tha]\n        else if (a instanceof Proton.Polar3D) {\n            this.tha = b * Proton.DR;\n            this.dirVec = a.toVector3D();\n            this._useV = false;\n        }\n\n        //[radius,vector,tha]\n        else {\n            this.radiusPan = Proton.createSpan(a);\n            this.dir = b.clone().normalize();\n            this.tha = c * Proton.DR;\n            this._useV = true;\n        }\n    };\n\n    Velocity.prototype.normalize = function(vr) {\n        return vr * Proton.MEASURE;\n    }\n\n    Velocity.prototype.initialize = function() {\n        var tha;\n        var normal = new Proton.Vector3D(0, 0, 1);\n        var v = new Proton.Vector3D(0, 0, 0);\n\n        return function initialize(target) {\n            tha = this.tha * Math.random();\n            this._useV && this.dirVec.copy(this.dir).scalar(this.radiusPan.getValue());\n\n            Proton.MathUtils.getNormal(this.dirVec, normal);\n            v.copy(this.dirVec).applyAxisAngle(normal, tha);\n            v.applyAxisAngle(this.dirVec.normalize(), Math.random() * Proton.PI * 2);\n\n            //use  axisRotate methods\n            //Proton.MathUtils.axisRotate(this.v1, this.dirVec, normal, tha);\n            //Proton.MathUtils.axisRotate(this.v2, this.v1, this.dirVec.normalize(), Math.random() * Proton.PI * 2);\n            target.v.copy(v);\n            return this;\n        };\n    }()\n\n    Proton.Velocity = Velocity;\n    Proton.V = Velocity;\n})(Proton);\n"
  },
  {
    "path": "src/math/ArraySpan.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * ArraySpan name get a random Color from a colors array\n     * @param {String|Array} colors - colors array\n     * @example \n     * var span = new Proton.ArraySpan([\"#fff\",\"#ff0\",\"#000\"]);\n     * or\n     * var span = new Proton.ArraySpan(\"#ff0\");\n     * @extends {Proton.Span}\n     * @constructor\n     */\n\n    function ArraySpan(colors) {\n        this._arr = Proton.Util.isArray(colors) ? colors : [colors];\n    }\n\n    Proton.Util.inherits(ArraySpan, Proton.Span);\n\n    /**\n     * getValue function\n     * @name get a random Color\n     * @return {string} a hex color\n     */\n    ArraySpan.prototype.getValue = function() {\n        var color = this._arr[(this._arr.length * Math.random()) >> 0];\n        \n        if (color == 'random' || color == 'Random')\n            return Proton.MathUtils.randomColor();\n        else\n            return color;\n    }\n\n    /**\n     * Proton.createArraySpan function\n     * @name get a instance of Span\n     * @param {number} a min number\n     * @param {number} b max number\n     * @param {number} c center number\n     * @return {number} return a instance of Span\n     */\n    Proton.createArraySpan = function(arr) {\n        if (!arr) return null;\n        if (arr instanceof Proton.ArraySpan)\n            return arr;\n        else \n            return new Proton.ArraySpan(arr);\n    }\n\n    Proton.ArraySpan = ArraySpan;\n\n})(Proton);\n"
  },
  {
    "path": "src/math/Box.js",
    "content": "(function(Proton, undefined) {\n    function Box(x, y, z, w, h, d) {\n        this.x = x;\n        this.y = y;\n        this.z = z;\n        this.width = w;\n        this.height = h;\n        this.depth = d;\n        this.bottom = this.y + this.height;\n        this.right = this.x + this.width;\n        this.right = this.x + this.width;\n    }\n\n\n    Box.prototype = {\n        contains: function(x, y, z) {\n            if (\n                x <= this.right &&\n                x >= this.x &&\n                y <= this.bottom &&\n                y >= this.y &&\n                z <= this.depth &&\n                z >= this.z\n            )\n                return true\n            else\n                return false\n        }\n    }\n\n    Proton.Box = Box;\n})(Proton);\n"
  },
  {
    "path": "src/math/Integration.js",
    "content": "//数值积分\n(function(Proton, undefined) {\n    var Integration = function(type) {\n        this.type = Proton.Util.initValue(type, Proton.EULER);\n    }\n\n    Integration.prototype = {\n        integrate: function(particles, time, damping) {\n            this.euler(particles, time, damping);\n        },\n\n        euler: function(particle, time, damping) {\n            if (!particle.sleep) {\n                particle.old.p.copy(particle.p);\n                particle.old.v.copy(particle.v);\n                particle.a.scalar(1 / particle.mass);\n                particle.v.add(particle.a.scalar(time));\n                particle.p.add(particle.old.v.scalar(time));\n                damping && particle.v.scalar(damping);\n                particle.a.clear();\n            }\n        }\n    }\n\n    Proton.Integration = Integration;\n})(Proton);\n"
  },
  {
    "path": "src/math/MathUtils.js",
    "content": "(function(Proton, undefined) {\n    var MathUtils = {\n        randomAToB: function(a, b, INT) {\n            if (!INT)\n                return a + Math.random() * (b - a);\n            else\n                return ((Math.random() * (b - a)) >> 0) + a;\n        },\n        randomFloating: function(center, f, INT) {\n            return MathUtils.randomAToB(center - f, center + f, INT);\n        },\n\n        randomZone: function(display) {\n\n        },\n\n        degreeTransform: function(a) {\n            return a * Proton.PI / 180;\n        },\n\n        toColor16: function getRGB(num) {\n            return \"#\" + num.toString(16);\n        },\n\n        randomColor: function() {\n            return '#' + ('00000' + (Math.random() * 0x1000000 << 0).toString(16)).slice(-6);\n        },\n\n        lerp: function(a, b, energy) {\n            return b + (a - b) * energy\n        },\n\n        getNormal: function(v, n) {\n            if (v.x == 0 && v.y == 0) {\n                if (v.z == 0)\n                    n.set(1, 0, 1);\n                else\n                    n.set(1, 1, -v.y / v.z);\n            } else {\n                if (v.x == 0)\n                    n.set(1, 0, 1);\n                else\n                    n.set(-v.y / v.x, 1, 1);\n            }\n\n            return n.normalize();\n        },\n\n        /** \n         * Rodrigues' Rotation Formula \n         * https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula\n         * v′ = vcos(θ) + k(k⋅v)(1−cos(θ)) + (k*v)sin(θ)\n         */\n        axisRotate: function(v0, v, k, tha) {\n            var cos = Math.cos(tha);\n            var sin = Math.sin(tha);\n            var p = k.dot(v) * (1 - cos);\n\n            v0.copy(k);\n            v0.cross(v).scalar(sin);\n            v0.addValue(v.x * cos, v.y * cos, v.z * cos);\n            v0.addValue(k.x * p, k.y * p, k.z * p);\n        }\n    }\n\n    Proton.MathUtils = MathUtils;\n})(Proton);\n"
  },
  {
    "path": "src/math/Polar3D.js",
    "content": "(function(Proton, undefined) {\n    var Polar3D = function(radius, theta, phi) {\n        this.radius = radius || 1;\n        this.phi = phi || 0;\n        this.theta = theta || 0;\n    }\n\n    Polar3D.prototype = {\n        set: function(radius, theta, phi) {\n            this.radius = radius || 1;\n            this.phi = phi || 0;\n            this.theta = theta || 0;\n\n            return this;\n        },\n\n        setRadius: function(radius) {\n            this.radius = radius;\n            return this;\n        },\n\n        setPhi: function(phi) {\n            this.phi = phi;\n            return this;\n        },\n\n        setTheta: function(theta) {\n            this.theta = theta;\n            return this;\n        },\n\n        copy: function(p) {\n            this.radius = p.radius;\n            this.phi = p.phi;\n            this.theta = p.theta;\n            return this;\n        },\n\n        toVector3D: function() {\n            return new Proton.Vector3D(this.getX(), this.getY(), this.getZ());\n        },\n\n        getX: function() {\n            return this.radius * Math.sin(this.theta) * Math.cos(this.phi);\n        },\n\n        getY: function() {\n            return -this.radius * Math.sin(this.theta) * Math.sin(this.phi);\n        },\n\n        getZ: function() {\n            return this.radius * Math.cos(this.theta);\n        },\n\n        normalize: function() {\n            this.radius = 1;\n            return this;\n        },\n\n        equals: function(v) {\n            return ((v.radius === this.radius) && (v.phi === this.phi) && (v.theta === this.theta));\n        },\n\n        clear: function() {\n            this.radius = 0.0;\n            this.phi = 0.0;\n            this.theta = 0.0;\n            return this;\n        },\n\n        clone: function() {\n            return new Polar3D(this.radius, this.phi, this.theta);\n        }\n    };\n\n\n    Proton.Polar3D = Polar3D;\n})(Proton);\n"
  },
  {
    "path": "src/math/Quaternion.js",
    "content": "(function(Proton, undefined) {\n\n    var Quaternion = function(x, y, z, w) {\n        this.x = x || 0;\n        this.y = y || 0;\n        this.z = z || 0;\n        this.w = (w !== undefined) ? w : 1;\n    };\n\n    Quaternion.prototype = {\n        set: function(x, y, z, w) {\n            this.x = x;\n            this.y = y;\n            this.z = z;\n            this.w = w;\n            return this;\n        },\n\n        clone: function() {\n            return new Proton.Quaternion(this.x, this.y, this.z, this.w);\n        },\n\n        copy: function(quaternion) {\n            this.x = quaternion.x;\n            this.y = quaternion.y;\n            this.z = quaternion.z;\n            this.w = quaternion.w;\n            return this;\n        },\n\n        setFromEuler: function(euler) {\n            // http://www.mathworks.com/matlabcentral/fileexchange/\n            //  20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\n            //  content/SpinCalc.m\n\n            var c1 = Math.cos(euler.x / 2);\n            var c2 = Math.cos(euler.y / 2);\n            var c3 = Math.cos(euler.z / 2);\n            var s1 = Math.sin(euler.x / 2);\n            var s2 = Math.sin(euler.y / 2);\n            var s3 = Math.sin(euler.z / 2);\n\n            this.x = s1 * c2 * c3 + c1 * s2 * s3;\n            this.y = c1 * s2 * c3 - s1 * c2 * s3;\n            this.z = c1 * c2 * s3 + s1 * s2 * c3;\n            this.w = c1 * c2 * c3 - s1 * s2 * s3;\n\n            return this;\n\n        },\n\n        setFromAxisAngle: function(axis, angle) {\n            // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\n            // assumes axis is normalized\n            var halfAngle = angle / 2,\n                s = Math.sin(halfAngle);\n            this.x = axis.x * s;\n            this.y = axis.y * s;\n            this.z = axis.z * s;\n            this.w = Math.cos(halfAngle);\n\n            return this;\n        },\n\n        // setFromUnitVectors: function() {\n        //     var v1, r;\n        //     var EPS = 0.000001;\n\n        //     return function(vFrom, vTo) {\n        //         if (v1 === undefined) v1 = new Proton.Vector3D();\n\n        //         r = vFrom.dot(vTo) + 1;\n        //         if (r < EPS) {\n        //             r = 0;\n        //             if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {\n        //                 v1.set(-vFrom.y, vFrom.x, 0);\n        //             } else {\n        //                 v1.set(0, -vFrom.z, vFrom.y);\n        //             }\n        //         } else {\n        //             v1.crossVectors(vFrom, vTo);\n        //         }\n\n        //         this.x = v1.x;\n        //         this.y = v1.y;\n        //         this.z = v1.z;\n        //         this.w = r;\n        //         return this.normalize();\n        //     };\n        // }(),\n\n        normalize: function() {\n\n            var l = this.length();\n\n            if (l === 0) {\n\n                this.x = 0;\n                this.y = 0;\n                this.z = 0;\n                this.w = 1;\n\n            } else {\n                l = 1 / l;\n                this.x *= l;\n                this.y *= l;\n                this.z *= l;\n                this.w *= l;\n\n            }\n            return this;\n        },\n\n        length: function() {\n\n            return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);\n\n        },\n\n        dot: function(v) {\n            return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\n        }\n    };\n\n    Proton.Quaternion = Quaternion;\n})(Proton);\n"
  },
  {
    "path": "src/math/Span.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Span Class. Get a random Number from a to b. Or from c-a to c+b\n     * @param {Number|Array} a - min number\n     * @param {Number} b - max number\n     * @param {Number} center - the center's z value  \n     * @example \n     * var span = new Proton.Span(0,30);\n     * or\n     * var span = new Proton.Span([\"#fff\",\"#ff0\",\"#000\"]);\n     * or\n     * var span = new Proton.Span(5,1,\"center\");\n     * @extends {Zone}\n     * @constructor\n     */\n    function Span(a, b, center) {\n        this._isArray = false;\n\n        if (Proton.Util.isArray(a)) {\n            this._isArray = true;\n            this.a = a;\n        } else {\n            this.a = Proton.Util.initValue(a, 1);\n            this.b = Proton.Util.initValue(b, this.a);\n            this._center = Proton.Util.initValue(center, false);\n        }\n    }\n\n    /**\n     * Span.getValue function\n     * @name get a random Number from a to b. Or get a random Number from c-a to c+b\n     * @param {number} INT or int\n     * @return {number} a random Number\n     */\n    Span.prototype = {\n        getValue: function(INT) {\n            if (this._isArray) {\n                return this.a[(this.a.length * Math.random()) >> 0];\n            } else {\n                if (!this._center)\n                    return Proton.MathUtils.randomAToB(this.a, this.b, INT);\n                else\n                    return Proton.MathUtils.randomFloating(this.a, this.b, INT);\n            }\n        }\n    }\n\n    /**\n     * Proton.createSpan function\n     * @name get a instance of Span\n     * @param {number} a min number\n     * @param {number} b max number\n     * @param {number} c center number\n     * @return {number} return a instance of Span\n     */\n    Proton.createSpan = function(a, b, c) {\n        if (a instanceof Span) return a;\n\n        if (b === undefined) {\n            return new Span(a);\n        } else {\n            if (c === undefined)\n                return new Span(a, b);\n            else\n                return new Span(a, b, c);\n        }\n    }\n\n    Proton.Span = Span;\n})(Proton);\n"
  },
  {
    "path": "src/math/Vector3D.js",
    "content": "//@author mrdoob / http://mrdoob.com/\n(function(Proton, undefined) {\n    var Vector3D = function(x, y, z) {\n        this.x = x || 0;\n        this.y = y || 0;\n        this.z = z || 0;\n    }\n\n    Vector3D.prototype = {\n        set: function(x, y, z) {\n            this.x = x;\n            this.y = y;\n            this.z = z;\n            return this;\n        },\n\n        setX: function(x) {\n            this.x = x;\n            return this;\n        },\n\n        setY: function(y) {\n            this.y = y;\n            return this;\n        },\n\n        setZ: function(z) {\n            this.z = z;\n            return this;\n        },\n\n        getGradient: function() {\n            if (this.x != 0)\n                return Math.atan2(this.y, this.x);\n            else if (this.y > 0)\n                return Proton.PI / 2;\n            else if (this.y < 0)\n                return -Proton.PI / 2;\n        },\n\n        copy: function(v) {\n            this.x = v.x;\n            this.y = v.y;\n            this.z = v.z;\n            return this;\n        },\n\n        add: function(v, w) {\n            if (w !== undefined) return this.addVectors(v, w);\n\n            this.x += v.x;\n            this.y += v.y;\n            this.z += v.z;\n\n            return this;\n\n        },\n\n        addValue: function(a, b, c) {\n            this.x += a;\n            this.y += b;\n            this.z += c;\n\n            return this;\n\n        },\n\n        addVectors: function(a, b) {\n            this.x = a.x + b.x;\n            this.y = a.y + b.y;\n            this.z = a.z + b.z;\n\n            return this;\n        },\n\n        addScalar: function(s) {\n            this.x += s;\n            this.y += s;\n            this.z += s;\n\n            return this;\n        },\n\n        sub: function(v, w) {\n            if (w !== undefined) return this.subVectors(v, w);\n\n            this.x -= v.x;\n            this.y -= v.y;\n            this.z -= v.z;\n\n            return this;\n        },\n\n        subVectors: function(a, b) {\n            this.x = a.x - b.x;\n            this.y = a.y - b.y;\n            this.z = a.z - b.z;\n            return this;\n        },\n\n        scalar: function(s) {\n            this.x *= s;\n            this.y *= s;\n            this.z *= s;\n\n            return this;\n        },\n\n        divideScalar: function(s) {\n            if (s !== 0) {\n                this.x /= s;\n                this.y /= s;\n                this.z /= s;\n            } else {\n                this.set(0, 0, 0);\n            }\n\n            return this;\n        },\n\n        negate: function() {\n            return this.scalar(-1);\n        },\n\n        dot: function(v) {\n            return this.x * v.x + this.y * v.y + this.z * v.z;\n        },\n\n        cross: function(v) {\n            var x = this.x,\n                y = this.y,\n                z = this.z;\n\n            this.x = y * v.z - z * v.y;\n            this.y = z * v.x - x * v.z;\n            this.z = x * v.y - y * v.x;\n\n            return this;\n        },\n\n        lengthSq: function() {\n            return this.x * this.x + this.y * this.y + this.z * this.z;\n        },\n\n        length: function() {\n            return Math.sqrt(this.lengthSq());\n        },\n\n        normalize: function() {\n            return this.divideScalar(this.length());\n        },\n\n        distanceTo: function(v) {\n            return Math.sqrt(this.distanceToSquared(v));\n        },\n\n        crossVectors: function(a, b) {\n\n            var ax = a.x,\n                ay = a.y,\n                az = a.z;\n            var bx = b.x,\n                by = b.y,\n                bz = b.z;\n\n            this.x = ay * bz - az * by;\n            this.y = az * bx - ax * bz;\n            this.z = ax * by - ay * bx;\n\n            return this;\n\n        },\n\n        // eulerFromDir: function() {\n        //     var quaternion, dir, up;\n\n        //     return function rotateFromDir(direction) {\n        //         if (quaternion === undefined) quaternion = new Proton.Quaternion();\n        //         if (dir === undefined) dir = new Proton.Vector3D;\n        //         if (up === undefined) up = new Proton.Vector3D(0, 0, 1);\n\n        //         //quaternion.setFromUnitVectors(up, dir.copy(direction).normalize());\n        //         console.log(quaternion.setFromUnitVectors(up, dir.copy(direction).normalize()));\n\n        //         this.applyQuaternion(quaternion.setFromUnitVectors(up, dir.copy(direction).normalize()));\n        //             console.log(this);\n        //         return this;\n        //     };\n        // }(),\n\n        eulerFromDir: function(dir) {\n            \n        },\n\n        applyEuler: function() {\n            var quaternion;\n\n            return function applyEuler(euler) {\n                if (quaternion === undefined) quaternion = new Proton.Quaternion();\n                this.applyQuaternion(quaternion.setFromEuler(euler));\n                return this;\n            };\n        }(),\n\n        applyAxisAngle: function() {\n            var quaternion;\n            return function applyAxisAngle(axis, angle) {\n                if (quaternion === undefined) quaternion = new Proton.Quaternion();\n                this.applyQuaternion(quaternion.setFromAxisAngle(axis, angle));\n                return this;\n            };\n        }(),\n\n        applyQuaternion: function(q) {\n            var x = this.x;\n            var y = this.y;\n            var z = this.z;\n\n            var qx = q.x;\n            var qy = q.y;\n            var qz = q.z;\n            var qw = q.w;\n\n            // calculate quat * vector\n\n            var ix = qw * x + qy * z - qz * y;\n            var iy = qw * y + qz * x - qx * z;\n            var iz = qw * z + qx * y - qy * x;\n            var iw = -qx * x - qy * y - qz * z;\n\n            // calculate result * inverse quat\n            this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;\n            this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;\n            this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;\n            return this;\n        },\n\n        distanceToSquared: function(v) {\n            var dx = this.x - v.x,\n                dy = this.y - v.y,\n                dz = this.z - v.z;\n\n            return dx * dx + dy * dy + dz * dz;\n        },\n\n        lerp: function(v, alpha) {\n            this.x += (v.x - this.x) * alpha;\n            this.y += (v.y - this.y) * alpha;\n            this.z += (v.z - this.z) * alpha;\n            return this;\n        },\n\n        equals: function(v) {\n            return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));\n        },\n\n        clear: function() {\n            this.x = 0.0;\n            this.y = 0.0;\n            this.z = 0.0;\n            return this;\n        },\n\n        clone: function() {\n            return new Proton.Vector3D(this.x, this.y, this.z);\n        },\n\n        toString: function() {\n            return \"x:\" + this.x + \"y:\" + this.y + \"z:\" + this.z;\n        }\n    };\n\n    Proton.Vector3D = Vector3D;\n})(Proton);\n"
  },
  {
    "path": "src/render/BaseRender.js",
    "content": "(function(Proton, undefined) {\n\n    function BaseRender() { this.name = \"BaseRender\"; }\n\n    BaseRender.prototype = {\n        init: function(proton) {\n            var self = this;\n            this.proton = proton;\n            \n            this.proton.addEventListener(\"PROTON_UPDATE\", function(proton) {\n                self.onProtonUpdate.call(self, proton);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_CREATED\", function(particle) {\n                self.onParticleCreated.call(self, particle);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_UPDATE\", function(particle) {\n                self.onParticleUpdate.call(self, particle);\n            });\n\n            this.proton.addEventListener(\"PARTICLE_DEAD\", function(particle) {\n                self.onParticleDead.call(self, particle);\n            });\n        },\n\n        remove: function(proton) {\n            // this.proton.removeEventListener(\"PROTON_UPDATE\", this.onProtonUpdate);\n            // this.proton.removeEventListener(\"PARTICLE_CREATED\", this.onParticleCreated);\n            // this.proton.removeEventListener(\"PARTICLE_UPDATE\", this.onParticleUpdate);\n            // this.proton.removeEventListener(\"PARTICLE_DEAD\", this.onParticleDead);\n            this.proton = null;\n        },\n\n        onParticleCreated: function(particle) {\n\n        },\n\n        onParticleUpdate: function(particle) {\n\n        },\n\n        onParticleDead: function(particle) {\n\n        },\n\n        onProtonUpdate: function(proton) {\n\n        }\n    }\n\n    Proton.BaseRender = BaseRender;\n})(Proton);\n"
  },
  {
    "path": "src/render/CustomRender.js",
    "content": "(function(Proton, undefined) {\n\n    function CustomRender() {\n        CustomRender._super_.call(this);\n        this.targetPool = new Proton.Pool();\n        this.materialPool = new Proton.Pool();\n        \n        this.name = \"CustomRender\";\n    }\n\n    Proton.Util.inherits(CustomRender, Proton.BaseRender);\n\n    CustomRender.prototype.onProtonUpdate = function() {};\n\n    CustomRender.prototype.onParticleCreated = function(particle) {\n        \n    };\n\n    CustomRender.prototype.onParticleUpdate = function(particle) {\n        \n    };\n\n    CustomRender.prototype.onParticleDead = function(particle) {\n        \n    };\n\n    Proton.CustomRender = CustomRender;\n})(Proton);\n"
  },
  {
    "path": "src/render/MeshRender.js",
    "content": "(function(Proton, undefined) {\n\n    function MeshRender(container) {\n        MeshRender._super_.call(this);\n        this.container = container;\n\n        this._targetPool = new Proton.Pool();\n        this._materialPool = new Proton.Pool();\n        this._body = new THREE.Mesh(\n            new THREE.BoxGeometry(50, 50, 50),\n            new THREE.MeshLambertMaterial({ color: \"#ff0000\" })\n        );\n        \n        this.name = \"MeshRender\";\n    }\n\n    Proton.Util.inherits(MeshRender, Proton.BaseRender);\n\n    MeshRender.prototype.onProtonUpdate = function() {};\n\n    MeshRender.prototype.onParticleCreated = function(particle) {\n        if (!particle.target) {\n            //set target\n            if (!particle.body) particle.body = this._body;\n            particle.target = this._targetPool.get(particle.body);\n            \n            //set material\n            if (particle.useAlpha || particle.useColor) {\n                particle.target.material.__puid = Proton.PUID.id(particle.body.material);;\n                particle.target.material = this._materialPool.get(particle.target.material);\n            }\n        }\n\n        if (particle.target) {\n            particle.target.position.copy(particle.p);\n            this.container.add(particle.target);\n        }\n    };\n\n    MeshRender.prototype.onParticleUpdate = function(particle) {\n        if (particle.target) {\n            particle.target.position.copy(particle.p);\n            particle.target.rotation.set(particle.rotation.x, particle.rotation.y, particle.rotation.z);\n            this.scale(particle);\n\n            if (particle.useAlpha) {\n                particle.target.material.opacity = particle.alpha;\n                particle.target.material.transparent = true;\n            }\n\n            if (particle.useColor) {\n                particle.target.material.color.copy(particle.color);\n            }\n        }\n    };\n\n    MeshRender.prototype.scale = function(particle) {\n        particle.target.scale.set(particle.scale, particle.scale, particle.scale);\n    }\n\n    MeshRender.prototype.onParticleDead = function(particle) {\n        if (particle.target) {\n            if (particle.useAlpha || particle.useColor)\n                this._materialPool.expire(particle.target.material);\n\n            this._targetPool.expire(particle.target);\n            this.container.remove(particle.target);\n            particle.target = null;\n        }\n    };\n\n    Proton.MeshRender = MeshRender;\n})(Proton);\n"
  },
  {
    "path": "src/render/PointsRender.js",
    "content": "(function(Proton, undefined) {\n\n    function PointsRender(ps) {\n        PointsRender._super_.call(this);\n        this.points = ps;\n        this.name = \"PointsRender\";\n    }\n\n    Proton.Util.inherits(PointsRender, Proton.BaseRender);\n\n    PointsRender.prototype.onProtonUpdate = function() {\n        \n    };\n\n    PointsRender.prototype.onParticleCreated = function(particle) {\n        if (!particle.target) {\n            particle.target = new THREE.Vector3();\n        }\n\n        particle.target.copy(particle.p);\n        this.points.geometry.vertices.push(particle.target);\n    };\n\n    PointsRender.prototype.onParticleUpdate = function(particle) {\n        if (particle.target) {\n            particle.target.copy(particle.p);\n        }\n    };\n\n    PointsRender.prototype.onParticleDead = function(particle) {\n        if (particle.target) {\n            var index = this.points.geometry.vertices.indexOf(particle.target);\n            if (index > -1)\n                this.points.geometry.vertices.splice(index, 1);\n            \n            particle.target = null;\n        }\n    };\n\n    Proton.PointsRender = PointsRender;\n})(Proton);\n"
  },
  {
    "path": "src/render/SpriteRender.js",
    "content": "(function(Proton, undefined) {\n\n    function SpriteRender(container) {\n        SpriteRender._super_.call(this, container);\n\n        this._body = new THREE.Sprite(new THREE.SpriteMaterial({ color: 0xffffff }));\n        this.name = \"SpriteRender\";\n    }\n\n    Proton.Util.inherits(SpriteRender, Proton.MeshRender);\n\n    SpriteRender.prototype.scale = function(particle) {\n        particle.target.scale.set(particle.scale * particle.radius, particle.scale * particle.radius, 1);\n    };\n\n    Proton.SpriteRender = SpriteRender;\n})(Proton);\n"
  },
  {
    "path": "src/utils/ColorUtil.js",
    "content": "(function(Proton, undefined) {\n    var ColorUtil = ColorUtil || {\n        getRGB: function(color) {\n            var rgb = {};\n            if (typeof color === 'number') {\n                hex = Math.floor(color);\n                rgb.r = (color >> 16 & 255) / 255;\n                rgb.g = (color >> 8 & 255) / 255;\n                rgb.b = (color & 255) / 255;\n            } else if (typeof color === 'string') {\n                var m;\n                if (m = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec(color)) {\n                    rgb.r = Math.min(255, parseInt(m[1], 10)) / 255;\n                    rgb.g = Math.min(255, parseInt(m[2], 10)) / 255;\n                    rgb.b = Math.min(255, parseInt(m[3], 10)) / 255;\n                } else if (m = /^\\#([A-Fa-f0-9]+)$/.exec(color)) {\n                    var hex = m[1];\n                    rgb.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255;\n                    rgb.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255;\n                    rgb.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255;\n                }\n            } else if (color instanceof THREE.Color) {\n                rgb.r = color.r;\n                rgb.g = color.g;\n                rgb.b = color.b;\n            }\n\n            return rgb;\n        }\n    };\n\n\n    Proton.ColorUtil = ColorUtil;\n})(Proton);\n"
  },
  {
    "path": "src/utils/PUID.js",
    "content": "(function(Proton, undefined) {\n    var PUID = PUID || {\n        _id: 0,\n        _uids: {},\n        id: function(obj) {\n            for (var id in this._uids) {\n                if (this._uids[id] == obj) return id;\n            }\n\n            var nid = \"PUID_\" + (this._id++);\n            this._uids[nid] = obj;\n            return nid;\n        },\n\n        hash: function(str) {\n            return;\n        }\n    }\n\n    Proton.PUID = PUID;\n})(Proton);\n"
  },
  {
    "path": "src/utils/THREEUtil.js",
    "content": "(function(Proton, undefined) {\n    var THREEUtil = {\n        toScreenPos: function() {\n            var vector = new THREE.Vector3();\n\n            return function(pos, camera, canvas) {\n                vector.copy(pos);\n                // map to normalized device coordinate (NDC) space\n                vector.project(camera);\n                // map to 2D screen space\n                vector.x = Math.round((vector.x + 1) * canvas.width / 2);\n                vector.y = Math.round((-vector.y + 1) * canvas.height / 2);\n                vector.z = 0;\n\n                return vector;\n            }\n        }(),\n\n        toSpacePos: function() {\n            var vector = new THREE.Vector3(),\n                dir = new THREE.Vector3(),\n                distance;\n\n            return function(pos, camera, canvas) {\n                vector.set((pos.x / canvas.width) * 2 - 1, -(pos.y / canvas.height) * 2 + 1, 0.5);\n                vector.unproject(camera);\n\n                dir.copy(vector.sub(camera.position).normalize());\n                distance = -camera.position.z / dir.z;\n                vector.copy(camera.position);\n                vector.add(dir.multiplyScalar(distance));\n\n                return vector;\n            }\n        }(),\n\n        getTexture: function() {\n            var store = {};\n\n            return function(img) {\n                if (img instanceof THREE.Texture) {\n                    return img;\n                } else if (typeof img == \"string\") {\n                    var id = Proton.PUID.hash(img);\n                    if (!store[id]) store[id] = new THREE.Texture(img);;\n                    return store[id];\n                } else if (img instanceof Image) {\n                    var id = Proton.PUID.hash(img.src);\n                    if (!store[id]) store[id] = new THREE.Texture(img);;\n                    return store[id];\n                }\n            }\n        }()\n    };\n\n    Proton.THREEUtil = THREEUtil;\n})(Proton);\n"
  },
  {
    "path": "src/utils/Util.js",
    "content": "(function(Proton, undefined) {\n    var Util = Util || {\n        initValue: function(value, defaults) {\n            var value = (value != null && value != undefined) ? value : defaults;\n            return value;\n        },\n\n        isArray: function(value) {\n            return Object.prototype.toString.call(value) === '[object Array]';\n        },\n\n        destroyArray: function(array) {\n            array.length = 0;\n        },\n\n        destroyObject: function(obj) {\n            for (var o in obj) delete obj[o];\n        },\n\n        isUndefined: function() {\n            for (var id in arguments) {\n                var arg = arguments[id];\n                if (arg !== undefined)\n                    return false;\n            }\n\n            return true;\n        },\n\n        setVectorByObj: function(target, pOBJ) {\n            if (pOBJ[\"x\"] !== undefined) target.p.x = pOBJ[\"x\"];\n            if (pOBJ[\"y\"] !== undefined) target.p.y = pOBJ[\"y\"];\n            if (pOBJ[\"z\"] !== undefined) target.p.z = pOBJ[\"z\"];\n\n            if (pOBJ[\"vx\"] !== undefined) target.v.x = pOBJ[\"vx\"];\n            if (pOBJ[\"vy\"] !== undefined) target.v.y = pOBJ[\"vy\"];\n            if (pOBJ[\"vz\"] !== undefined) target.v.z = pOBJ[\"vz\"];\n\n            if (pOBJ[\"ax\"] !== undefined) target.a.x = pOBJ[\"ax\"];\n            if (pOBJ[\"ay\"] !== undefined) target.a.y = pOBJ[\"ay\"];\n            if (pOBJ[\"az\"] !== undefined) target.a.z = pOBJ[\"az\"];\n\n            if (pOBJ[\"p\"] !== undefined) target.p.copy(pOBJ[\"p\"]);\n            if (pOBJ[\"v\"] !== undefined) target.v.copy(pOBJ[\"v\"]);\n            if (pOBJ[\"a\"] !== undefined) target.a.copy(pOBJ[\"a\"]);\n\n            if (pOBJ[\"position\"] !== undefined) target.p.copy(pOBJ[\"position\"]);\n            if (pOBJ[\"velocity\"] !== undefined) target.v.copy(pOBJ[\"velocity\"]);\n            if (pOBJ[\"accelerate\"] !== undefined) target.a.copy(pOBJ[\"accelerate\"]);\n        },\n\n        //set prototype\n        setPrototypeByObj: function(target, proObj, filters) {\n            for (var key in proObj) {\n                if (target.hasOwnProperty(key)) {\n                    if (filters) {\n                        if (filters.indexOf(key) < 0) target[key] = Util._getValue(proObj[key]);\n                    } else {\n                        target[key] = Util._getValue(proObj[key]);\n                    }\n                }\n            }\n\n            return target;\n        },\n\n        _getValue: function(pan) {\n            if (pan instanceof Span)\n                return pan.getValue();\n            else\n                return pan;\n        },\n\n        inherits: function(subClass, superClass) {\n            subClass._super_ = superClass;\n            if (Object['create']) {\n                subClass.prototype = Object.create(superClass.prototype, {\n                    constructor: { value: subClass }\n                });\n            } else {\n                var F = function() {};\n                F.prototype = superClass.prototype;\n                subClass.prototype = new F();\n                subClass.prototype.constructor = subClass;\n            }\n        }\n    };\n\n    Proton.Util = Util;\n})(Proton);\n"
  },
  {
    "path": "src/zone/BoxZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * BoxZone is a box zone\n     * @param {Number|Proton.Vector3D} x - the position's x value or a Proton.Vector3D Object\n     * @param {Number} y - the position's y value \n     * @param {Number} z - the position's z value \n     * @param {Number} w - the Box's width \n     * @param {Number} h - the Box's height \n     * @param {Number} d - the Box's depth \n     * @example \n     * var boxZone = new Proton.BoxZone(0,0,0,50,50,50);\n     * or\n     * var boxZone = new Proton.BoxZone(new Proton.Proton.Vector3D(0,0,0), 50, 50, 50);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n    function BoxZone(a, b, c, d, e, f) {\n        var x, y, z, w, h, d;\n        BoxZone._super_.call(this);\n\n        if (Proton.Util.isUndefined(b, c, d, e, f)) {\n            x = y = z = 0;\n            w = h = d = (a || 100);\n        } else if (Proton.Util.isUndefined(d, e, f)) {\n            x = y = z = 0;\n            w = a;\n            h = b;\n            d = c;\n        } else {\n            x = a;\n            y = b;\n            z = c;\n            w = d;\n            h = e;\n            d = f;\n        }\n\n        this.x = x;\n        this.y = y;\n        this.z = z;\n        this.width = w;\n        this.height = h;\n        this.depth = d;\n\n        //\n        this.friction = 0.85;\n        this.max = 6;\n    }\n\n    Proton.Util.inherits(BoxZone, Proton.Zone);\n    BoxZone.prototype.getPosition = function() {\n        this.vector.x = this.x + Proton.MathUtils.randomAToB(-.5, .5) * this.width;\n        this.vector.y = this.y + Proton.MathUtils.randomAToB(-.5, .5) * this.height;\n        this.vector.z = this.z + Proton.MathUtils.randomAToB(-.5, .5) * this.depth;\n        return this.vector;\n    }\n\n    BoxZone.prototype._dead = function(particle) {\n        if (particle.p.x + particle.radius < this.x - this.width / 2)\n            particle.dead = true;\n        else if (particle.p.x - particle.radius > this.x + this.width / 2)\n            particle.dead = true;\n\n        if (particle.p.y + particle.radius < this.y - this.height / 2)\n            particle.dead = true;\n        else if (particle.p.y - particle.radius > this.y + this.height / 2)\n            particle.dead = true;\n\n        if (particle.p.z + particle.radius < this.z - this.depth / 2)\n            particle.dead = true;\n        else if (particle.p.z - particle.radius > this.z + this.depth / 2)\n            particle.dead = true;\n    }\n\n    BoxZone.prototype._bound = function(particle) {\n        if (particle.p.x - particle.radius < this.x - this.width / 2) {\n            particle.p.x = this.x - this.width / 2 + particle.radius;\n            particle.v.x *= -this.friction;\n            this._static(particle, \"x\");\n        } else if (particle.p.x + particle.radius > this.x + this.width / 2) {\n            particle.p.x = this.x + this.width / 2 - particle.radius;\n            particle.v.x *= -this.friction;\n            this._static(particle, \"x\");\n        }\n\n        if (particle.p.y - particle.radius < this.y - this.height / 2) {\n            particle.p.y = this.y - this.height / 2 + particle.radius;\n            particle.v.y *= -this.friction;\n            this._static(particle, \"y\");\n        } else if (particle.p.y + particle.radius > this.y + this.height / 2) {\n            particle.p.y = this.y + this.height / 2 - particle.radius;\n            particle.v.y *= -this.friction;\n            this._static(particle, \"y\");\n        }\n\n        if (particle.p.z - particle.radius < this.z - this.depth / 2) {\n            particle.p.z = this.z - this.depth / 2 + particle.radius;\n            particle.v.z *= -this.friction;\n            this._static(particle, \"z\");\n        } else if (particle.p.z + particle.radius > this.z + this.depth / 2) {\n            particle.p.z = this.z + this.depth / 2 - particle.radius;\n            particle.v.z *= -this.friction;\n            this._static(particle, \"z\");\n        }\n    }\n\n    BoxZone.prototype._static = function(particle, axis) {\n        if (particle.v[axis] * particle.a[axis] > 0) return;\n        if (Math.abs(particle.v[axis]) < Math.abs(particle.a[axis]) * 0.0167 * this.max) {\n            particle.v[axis] = 0;\n            particle.a[axis] = 0;\n        }\n    }\n\n    BoxZone.prototype._cross = function(particle) {\n        if (particle.p.x + particle.radius < this.x - this.width / 2 && particle.v.x <= 0)\n            particle.p.x = this.x + this.width / 2 + particle.radius;\n        else if (particle.p.x - particle.radius > this.x + this.width / 2 && particle.v.x >= 0)\n            particle.p.x = this.x - this.width / 2 - particle.radius;\n\n        if (particle.p.y + particle.radius < this.y - this.height / 2 && particle.v.y <= 0)\n            particle.p.y = this.y + this.height / 2 + particle.radius;\n        else if (particle.p.y - particle.radius > this.y + this.height / 2 && particle.v.y >= 0)\n            particle.p.y = this.y - this.height / 2 - particle.radius;\n\n        if (particle.p.z + particle.radius < this.z - this.depth / 2 && particle.v.z <= 0)\n            particle.p.z = this.z + this.depth / 2 + particle.radius;\n        else if (particle.p.z - particle.radius > this.z + this.depth / 2 && particle.v.z >= 0)\n            particle.p.z = this.z - this.depth / 2 - particle.radius;\n    }\n\n    Proton.BoxZone = BoxZone;\n})(Proton);\n"
  },
  {
    "path": "src/zone/LineZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * LineZone is a 3d line zone\n     * @param {Number|Vector3D} x1 - the line's start point of x value or a Vector3D Object\n     * @param {Number|Vector3D} y1 - the line's start point of y value or a Vector3D Object\n     * @param {Number} z1 - the line's start point of z value \n     * @param {Number} x2 - the line's end point of x value \n     * @param {Number} y2 - the line's end point of y value \n     * @param {Number} z2 - the line's end point of z value \n     * @example \n     * var lineZone = new Proton.LineZone(0,0,0,100,100,0);\n     * or\n     * var lineZone = new Proton.LineZone(new Proton.Vector3D(0,0,0),new Proton.Vector3D(100,100,0));\n     * @extends {Zone}\n     * @constructor\n     */\n    function LineZone(x1, y1, z1, x2, y2, z2) {\n        LineZone._super_.call(this);\n        if (x1 instanceof Proton.Vector3D) {\n            this.x1 = x1.x;\n            this.y1 = x1.y;\n            this.z1 = x1.z;\n\n            this.x2 = x2.x;\n            this.y2 = x2.y;\n            this.z2 = x2.z;\n        } else {\n            this.x1 = x1;\n            this.y1 = y1;\n            this.z1 = z1;\n\n            this.x2 = x2;\n            this.y2 = y2;\n            this.z2 = z2;\n        }\n    }\n\n\n    Proton.Util.inherits(LineZone, Proton.Zone);\n    LineZone.prototype.getPosition = function() {\n        this.random = Math.random();\n        this.vector.x = this.x1 + this.random * (this.x2 - this.x1);\n        this.vector.y = this.y1 + this.random * (this.y2 - this.y1);\n        this.vector.z = this.z1 + this.random * (this.z2 - this.z1);\n        return this.vector;\n    }\n\n    LineZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry LineZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.LineZone = LineZone;\n})(Proton);\n"
  },
  {
    "path": "src/zone/MeshZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * MeshZone is a threejs mesh zone\n     * @param {Geometry|Mesh} geometry - a THREE.Geometry or THREE.Mesh object\n     * @example \n     * var geometry = new THREE.CylinderGeometry( 5, 5, 20, 32 );\n     * var cylinder = new THREE.Mesh( geometry, material );\n     * var meshZone = new Proton.MeshZone(geometry);\n     * or\n     * var meshZone = new Proton.MeshZone(cylinder);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n\n    function MeshZone(geometry, scale) {\n        MeshZone._super_.call(this);\n        if (geometry instanceof THREE.Geometry) {\n            this.geometry = geometry;\n        } else {\n            this.geometry = geometry.geometry;\n        }\n\n        this.scale = scale || 1;\n    }\n\n    Proton.Util.inherits(MeshZone, Proton.Zone);\n    MeshZone.prototype.getPosition = function() {\n        var vertices = this.geometry.vertices;\n        var rVector = vertices[(vertices.length * Math.random()) >> 0];\n        this.vector.x = rVector.x * this.scale;\n        this.vector.y = rVector.y * this.scale;\n        this.vector.z = rVector.z * this.scale;\n        return this.vector;\n    }\n\n    MeshZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry MeshZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.MeshZone = MeshZone;\n})(Proton);\n"
  },
  {
    "path": "src/zone/PointZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * PointZone is a point zone\n     * @param {Number|Vector3D} x - the center's x value or a Vector3D Object\n     * @param {Number} y - the center's y value\n     * @param {Number} z - the center's z value  \n     * @example \n     * var pointZone = new Proton.PointZone(0,30,10);\n     * or\n     * var pointZone = new Proton.PointZone(new Proton.Vector3D(0,30,10));\n     * @extends {Zone}\n     * @constructor\n     */\n    function PointZone(a, b, c) {\n        var x, y, z;\n        PointZone._super_.call(this);\n\n        if (Proton.Util.isUndefined(a, b, c)) {\n            x = y = z = 0;\n        } else {\n            x = a;\n            y = b;\n            z = c;\n        }\n\n        this.x = x;\n        this.y = y;\n        this.z = z;\n    }\n\n    Proton.Util.inherits(PointZone, Proton.Zone);\n    PointZone.prototype.getPosition = function() {\n        this.vector.x = this.x;\n        this.vector.y = this.y;\n        this.vector.z = this.z;\n        return this.vector;\n    }\n\n    PointZone.prototype.crossing = function(particle) {\n        if (this.log) {\n            console.error('Sorry PointZone does not support crossing method');\n            this.log = false;\n        }\n    }\n\n    Proton.PointZone = PointZone;\n})(Proton);\n"
  },
  {
    "path": "src/zone/ScreenZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * ScreenZone is a 3d line zone\n     * @param {Number|Vector3D} x1 - the line's start point of x value or a Vector3D Object\n     * @param {Number|Vector3D} y1 - the line's start point of y value or a Vector3D Object\n     * @param {Number} z1 - the line's start point of z value \n     * @param {Number} x2 - the line's end point of x value \n     * @param {Number} y2 - the line's end point of y value \n     * @param {Number} z2 - the line's end point of z value \n     * @example \n     * var lineZone = new Proton.ScreenZone(0,0,0,100,100,0);\n     * or\n     * var lineZone = new Proton.ScreenZone(new Proton.Vector3D(0,0,0),new Proton.Vector3D(100,100,0));\n     * @extends {Zone}\n     * @constructor\n     */\n    function ScreenZone(camera, renderer, dis, dir) {\n        ScreenZone._super_.call(this);\n\n        this.camera = camera;\n        this.renderer = renderer;\n        this.dis = dis || 20;\n        dir = dir || \"1234\";\n        for (var i = 1; i < 5; i++)\n            this[\"d\" + i] = dir.indexOf(i + \"\") >= 0;\n\n        this.name = \"ScreenZone\";\n    }\n\n\n    Proton.Util.inherits(ScreenZone, Proton.Zone);\n    ScreenZone.prototype.getPosition = function() {\n        var vec2 = new Proton.Vector3D,\n            canvas;\n\n        return function() {\n            canvas = this.renderer.domElement;\n            vec2.x = Math.random() * canvas.width;\n            vec2.y = Math.random() * canvas.height;\n            this.vector.copy(Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas));\n            return this.vector;\n        }\n    }();\n\n    ScreenZone.prototype._dead = function(particle) {\n        var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n        var canvas = this.renderer.domElement;\n\n        if ((pos.y + particle.radius < -this.dis) && this.d1) {\n            particle.dead = true;\n        } else if ((pos.y - particle.radius > canvas.height + this.dis) && this.d3) {\n            particle.dead = true;\n        }\n\n        if ((pos.x + particle.radius < -this.dis) && this.d4) {\n            particle.dead = true;\n        } else if ((pos.x - particle.radius > canvas.width + this.dis) && this.d2) {\n            particle.dead = true;\n        }\n    }\n\n    ScreenZone.prototype._cross = function() {\n        var vec2 = new Proton.Vector3D;\n        return function(particle) {\n            var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n            var canvas = this.renderer.domElement;\n\n            if (pos.y + particle.radius < -this.dis) {\n                vec2.x = pos.x;\n                vec2.y = canvas.height + this.dis + particle.radius;\n                particle.p.y = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).y;\n            } else if (pos.y - particle.radius > canvas.height + this.dis) {\n                vec2.x = pos.x;\n                vec2.y = -this.dis - particle.radius;\n                particle.p.y = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).y;\n            }\n\n            if (pos.x + particle.radius < -this.dis) {\n                vec2.y = pos.y;\n                vec2.x = canvas.width + this.dis + particle.radius;\n                particle.p.x = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).x;\n            } else if (pos.x - particle.radius > canvas.width + this.dis) {\n                vec2.y = pos.y;\n                vec2.x = -this.dis - particle.radius;\n                particle.p.x = Proton.THREEUtil.toSpacePos(vec2, this.camera, canvas).x;\n            }\n        }\n    }();\n\n    ScreenZone.prototype._bound = function(particle) {\n        var pos = Proton.THREEUtil.toScreenPos(particle.p, this.camera, this.renderer.domElement);\n        var canvas = this.renderer.domElement;\n\n        if (pos.y + particle.radius < -this.dis) {\n            particle.v.y *= -1;\n        } else if (pos.y - particle.radius > canvas.height + this.dis) {\n            particle.v.y *= -1;\n        }\n\n        if (pos.x + particle.radius < -this.dis) {\n            particle.v.y *= -1;\n        } else if (pos.x - particle.radius > canvas.width + this.dis) {\n            particle.v.y *= -1;\n        }\n    }\n\n    Proton.ScreenZone = ScreenZone;\n})(Proton);\n"
  },
  {
    "path": "src/zone/SphereZone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * SphereZone is a sphere zone\n     * @param {Number|Vector3D} x - the center's x value or a Vector3D Object\n     * @param {Number} y - the center's y value or the Sphere's radius \n     * @param {Number} z - the center's z value \n     * @param {Number} r - the Sphere's radius \n     * @example \n     * var sphereZone = new Proton.SphereZone(0,0,0,100);\n     * var sphereZone = new Proton.SphereZone(new Proton.Vector3D(0,0,0),100);\n     * @extends {Proton.Zone}\n     * @constructor\n     */\n    function SphereZone(a, b, c, d) {\n        var x, y, z, r;\n        SphereZone._super_.call(this);\n        if (Proton.Util.isUndefined(b, c, d)) {\n            x = y = z = 0;\n            r = (a || 100);\n        } else {\n            x = a;\n            y = b;\n            z = c;\n            r = d;\n        }\n\n        this.x = x;\n        this.y = x;\n        this.z = x;\n        this.radius = r;\n        this.tha = this.phi = 0;\n    }\n\n    Proton.Util.inherits(SphereZone, Proton.Zone);\n    SphereZone.prototype.getPosition = function() {\n        var tha, phi, r;\n        return function() {\n            this.random = Math.random();\n\n            r = this.random * this.radius;\n            tha = Proton.PI * Math.random(); //[0-pi]\n            phi = Proton.PI * 2 * Math.random(); //[0-2pi]\n\n            this.vector.x = this.x + r * Math.sin(tha) * Math.cos(phi);\n            this.vector.y = this.y + r * Math.sin(phi) * Math.sin(tha);\n            this.vector.z = this.z + r * Math.cos(tha);\n\n            return this.vector;\n        }\n    }();\n\n    SphereZone.prototype._dead = function(particle) {\n        var d = particle.p.distanceTo(this);\n        if (d - particle.radius > this.radius) particle.dead = true;\n    }\n\n    SphereZone.prototype._bound = function() {\n        var normal = new Proton.Vector3D,\n            v = new Proton.Vector3D,\n            k;\n\n        return function(particle) {\n            var d = particle.p.distanceTo(this);\n            if (d + particle.radius >= this.radius) {\n                normal.copy(particle.p).sub(this).normalize();\n                v.copy(particle.v);\n                k = 2 * v.dot(normal);\n                particle.v.sub(normal.scalar(k));\n            }\n        }\n    }();\n\n    SphereZone.prototype._cross = function(particle) {\n        if (this.log) {\n            console.error('Sorry SphereZone does not support _cross method');\n            this.log = false;\n        }\n    }\n\n    Proton.SphereZone = SphereZone;\n\n})(Proton);\n"
  },
  {
    "path": "src/zone/Zone.js",
    "content": "(function(Proton, undefined) {\n    /**\n     * Zone is a base class.\n     * @constructor\n     */\n    function Zone() {\n        this.vector = new Proton.Vector3D(0, 0, 0);\n        this.random = 0;\n        this.crossType = \"dead\";\n        this.log = true;\n    }\n\n    Zone.prototype = {\n        getPosition: function() {\n            return null;\n        },\n\n        crossing: function(particle) {\n            switch (this.crossType) {\n                case \"bound\":\n                    this._bound(particle);\n                    break;\n\n                case \"cross\":\n                    this._cross(particle);\n                    break;\n\n                case \"dead\":\n                    this._dead(particle);\n                    break;\n            }\n        },\n\n        _dead: function(particle) {},\n        _bound: function(particle) {},\n        _cross: function(particle) {},\n    };\n\n    Proton.Zone = Zone;\n})(Proton);\n"
  }
]