Pārlūkot izejas kodu

add some reposity

night-cherry 3 nedēļas atpakaļ
vecāks
revīzija
3584a54517
100 mainītis faili ar 32443 papildinājumiem un 1 dzēšanām
  1. 0 0
      lib/vue.esm-browser.js
  2. 0 0
      lib/vue.global.js
  3. BIN
      media/texture/envolope.jpg
  4. BIN
      media/texture/冰块-01.png
  5. BIN
      media/texture/冰块-02.png
  6. BIN
      media/texture/冰块-03-01.png
  7. BIN
      media/texture/冰块-04-01.png
  8. BIN
      media/texture/哭泣的黑曜石-01.png
  9. BIN
      media/texture/基岩-01.png
  10. BIN
      media/texture/樱花木板-01.png
  11. BIN
      media/texture/樱花木板2.png
  12. BIN
      media/texture/沙子.png
  13. BIN
      media/texture/白墙-01.png
  14. BIN
      media/texture/粉玻璃-01.jpg
  15. BIN
      media/texture/蓝墙.jpg
  16. 19 1
      node_modules/.package-lock.json
  17. 37 0
      node_modules/three-orbitcontrols-ts/.npmignore
  18. 21 0
      node_modules/three-orbitcontrols-ts/LICENSE
  19. 33 0
      node_modules/three-orbitcontrols-ts/README.md
  20. 105 0
      node_modules/three-orbitcontrols-ts/dist/index.d.ts
  21. 540 0
      node_modules/three-orbitcontrols-ts/dist/index.js
  22. 3 0
      node_modules/three-orbitcontrols-ts/mocha.opts
  23. 21 0
      node_modules/three-orbitcontrols-ts/node_modules/three/LICENSE
  24. 4996 0
      node_modules/three-orbitcontrols-ts/node_modules/three/build/three.js
  25. 349 0
      node_modules/three-orbitcontrols-ts/node_modules/three/build/three.min.js
  26. 4990 0
      node_modules/three-orbitcontrols-ts/node_modules/three/build/three.module.js
  27. 13 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/LICENSE
  28. 2 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/README
  29. 190 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/NOTICE
  30. 18 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/README.txt
  31. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_bold.typeface.json
  32. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_mono_regular.typeface.json
  33. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_regular.typeface.json
  34. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_serif_bold.typeface.json
  35. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_serif_regular.typeface.json
  36. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/gentilis_bold.typeface.json
  37. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/gentilis_regular.typeface.json
  38. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/helvetiker_bold.typeface.json
  39. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/helvetiker_regular.typeface.json
  40. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/optimer_bold.typeface.json
  41. 0 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/optimer_regular.typeface.json
  42. BIN
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/ttf/kenpixel.ttf
  43. 115 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/AnimationClipCreator.js
  44. 182 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BlendCharacter.js
  45. 207 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BlendCharacterGui.js
  46. 187 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BufferGeometryUtils.js
  47. 407 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Car.js
  48. 330 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Cloth.js
  49. 489 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ConvexObjectBreaker.js
  50. 331 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/CurveExtras.js
  51. 78 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Detector.js
  52. 370 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/GPUComputationRenderer.js
  53. 508 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/GPUParticleSystem.js
  54. 65 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Gyroscope.js
  55. 71 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ImprovedNoise.js
  56. 254 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MD2Character.js
  57. 560 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MD2CharacterComplex.js
  58. 1044 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MarchingCubes.js
  59. 302 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Mirror.js
  60. 69 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MorphAnimMesh.js
  61. 73 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MorphAnimation.js
  62. 359 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Ocean.js
  63. 2137 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Octree.js
  64. 23 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/PRNG.js
  65. 269 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ParametricGeometries.js
  66. 544 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/RollerCoaster.js
  67. 295 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderGodRays.js
  68. 692 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderSkin.js
  69. 322 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderTerrain.js
  70. 331 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderToon.js
  71. 324 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/SimplexNoise.js
  72. 229 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/SkyShader.js
  73. 280 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/TimelinerController.js
  74. 602 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/TypedArrayUtils.js
  75. 141 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/UCSCharacter.js
  76. 447 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Volume.js
  77. 217 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/VolumeSlice.js
  78. 297 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/WaterShader.js
  79. 416 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/animation/CCDIKSolver.js
  80. 1200 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/animation/MMDPhysics.js
  81. 188 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/cameras/CinematicCamera.js
  82. 230 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/cameras/CombinedCamera.js
  83. 111 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/DeviceOrientationControls.js
  84. 193 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/DragControls.js
  85. 293 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/EditorControls.js
  86. 300 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/FirstPersonControls.js
  87. 293 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/FlyControls.js
  88. 1016 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/OrbitControls.js
  89. 636 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/OrthographicTrackballControls.js
  90. 69 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/PointerLockControls.js
  91. 623 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/TrackballControls.js
  92. 1159 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/TransformControls.js
  93. 173 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/VRControls.js
  94. 39 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/gui.js
  95. 111 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/scenes.js
  96. 161 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/transition.js
  97. 65 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSCurve.js
  98. 55 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSSurface.js
  99. 472 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSUtils.js
  100. 152 0
      node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/effects/AnaglyphEffect.js

+ 0 - 0
utils/vue.esm-browser.js → lib/vue.esm-browser.js


+ 0 - 0
utils/vue.global.js → lib/vue.global.js


BIN
media/texture/envolope.jpg


BIN
media/texture/冰块-01.png


BIN
media/texture/冰块-02.png


BIN
media/texture/冰块-03-01.png


BIN
media/texture/冰块-04-01.png


BIN
media/texture/哭泣的黑曜石-01.png


BIN
media/texture/基岩-01.png


BIN
media/texture/樱花木板-01.png


BIN
media/texture/樱花木板2.png


BIN
media/texture/沙子.png


BIN
media/texture/白墙-01.png


BIN
media/texture/粉玻璃-01.jpg


BIN
media/texture/蓝墙.jpg


+ 19 - 1
node_modules/.package-lock.json

@@ -1,7 +1,7 @@
 {
   "name": "node_project",
   "version": "1.0.0",
-  "lockfileVersion": 2,
+  "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "node_modules/@ampproject/remapping": {
@@ -3873,6 +3873,24 @@
       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
       "dev": true
     },
+    "node_modules/three": {
+      "version": "0.176.0",
+      "resolved": "https://registry.npmmirror.com/three/-/three-0.176.0.tgz",
+      "integrity": "sha512-PWRKYWQo23ojf9oZSlRGH8K09q7nRSWx6LY/HF/UUrMdYgN9i1e2OwJYHoQjwc6HF/4lvvYLC5YC1X8UJL2ZpA=="
+    },
+    "node_modules/three-orbitcontrols-ts": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmmirror.com/three-orbitcontrols-ts/-/three-orbitcontrols-ts-0.1.2.tgz",
+      "integrity": "sha512-HG45dhJX4010lt/Ohk2d2K0kBaxCS6NLO3+wG9BDfMM5ddH7zMPuF3fhcn8vI4eqcSITtid0OoHEttHhjkIKEQ==",
+      "dependencies": {
+        "three": "^0.83.0"
+      }
+    },
+    "node_modules/three-orbitcontrols-ts/node_modules/three": {
+      "version": "0.83.0",
+      "resolved": "https://registry.npmmirror.com/three/-/three-0.83.0.tgz",
+      "integrity": "sha512-x9TqsmvhHG/Lw16Zi9zbJ0ho+kP8SgIfsz8dJYZbeWaFWoVwdXKolQQAftkUlpuKDys1+6SZIBHoA2QdoZKByQ=="
+    },
     "node_modules/tslib": {
       "version": "2.8.1",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",

+ 37 - 0
node_modules/three-orbitcontrols-ts/.npmignore

@@ -0,0 +1,37 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules
+jspm_packages
+
+# Optional npm cache directory
+.npm
+
+# Optional REPL history
+.node_repl_history

+ 21 - 0
node_modules/three-orbitcontrols-ts/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Nicolas Panel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 33 - 0
node_modules/three-orbitcontrols-ts/README.md

@@ -0,0 +1,33 @@
+ThreeJS OrbitControls as a standalone and typescript compatible npm module.
+
+# Installation
+```shell
+npm install --save three-orbitcontrols-ts
+```
+
+# Usage
+```js
+import * as THREE from 'three';
+import { OrbitControls } from 'three-orbitcontrols-ts';
+
+const camera = new THREE.SomeCamera(...);
+const controls = new OrbitControls(camera, renderer.domElement);
+
+// How far you can orbit vertically, upper and lower limits.
+controls.minPolarAngle = 0;
+controls.maxPolarAngle = Math.PI;
+
+
+// How far you can dolly in and out ( PerspectiveCamera only )
+controls.minDistance = 0;
+controls.maxDistance = Infinity;
+
+this.enableZoom = true; // Set to false to disable zooming
+this.zoomSpeed = 1.0;
+
+
+controls.enablePan = true; // Set to false to disable panning (ie vertical and horizontal translations)
+```
+
+# Credit
+All credit goes to [OrbitControls.js](https://github.com/mrdoob/three.js/blob/master/examples/js/controls/OrbitControls.js) contributors.

+ 105 - 0
node_modules/three-orbitcontrols-ts/dist/index.d.ts

@@ -0,0 +1,105 @@
+/// <reference types="three" />
+import * as THREE from 'three';
+/**
+* @author qiao / https://github.com/qiao
+* @author mrdoob / http://mrdoob.com
+* @author alteredq / http://alteredqualia.com/
+* @author WestLangley / http://github.com/WestLangley
+* @author erich666 / http://erichaines.com
+* @author nicolaspanel / http://github.com/nicolaspanel
+*
+* This set of controls performs orbiting, dollying (zooming), and panning.
+* Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+*    Orbit - left mouse / touch: one finger move
+*    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+*    Pan - right mouse, or arrow keys / touch: three finger swipe
+*/
+export declare class OrbitControls extends THREE.EventDispatcher {
+    object: THREE.Camera;
+    domElement: HTMLElement | HTMLDocument;
+    window: Window;
+    enabled: boolean;
+    target: THREE.Vector3;
+    enableZoom: boolean;
+    zoomSpeed: number;
+    minDistance: number;
+    maxDistance: number;
+    enableRotate: boolean;
+    rotateSpeed: number;
+    enablePan: boolean;
+    keyPanSpeed: number;
+    autoRotate: boolean;
+    autoRotateSpeed: number;
+    minZoom: number;
+    maxZoom: number;
+    minPolarAngle: number;
+    maxPolarAngle: number;
+    minAzimuthAngle: number;
+    maxAzimuthAngle: number;
+    enableKeys: boolean;
+    keys: {
+        LEFT: number;
+        UP: number;
+        RIGHT: number;
+        BOTTOM: number;
+    };
+    mouseButtons: {
+        ORBIT: THREE.MOUSE;
+        ZOOM: THREE.MOUSE;
+        PAN: THREE.MOUSE;
+    };
+    enableDamping: boolean;
+    dampingFactor: number;
+    private spherical;
+    private sphericalDelta;
+    private scale;
+    private target0;
+    private position0;
+    private zoom0;
+    private state;
+    private panOffset;
+    private zoomChanged;
+    private rotateStart;
+    private rotateEnd;
+    private rotateDelta;
+    private panStart;
+    private panEnd;
+    private panDelta;
+    private dollyStart;
+    private dollyEnd;
+    private dollyDelta;
+    private updateLastPosition;
+    private updateOffset;
+    private updateQuat;
+    private updateLastQuaternion;
+    private updateQuatInverse;
+    private panLeftV;
+    private panUpV;
+    private panInternalOffset;
+    private onContextMenu;
+    private onMouseUp;
+    private onMouseDown;
+    private onMouseMove;
+    private onMouseWheel;
+    private onTouchStart;
+    private onTouchEnd;
+    private onTouchMove;
+    private onKeyDown;
+    constructor(object: THREE.Camera, domElement?: HTMLElement, domWindow?: Window);
+    update(): boolean;
+    panLeft(distance: number, objectMatrix: any): void;
+    panUp(distance: number, objectMatrix: any): void;
+    pan(deltaX: number, deltaY: number): void;
+    dollyIn(dollyScale: any): void;
+    dollyOut(dollyScale: any): void;
+    getAutoRotationAngle(): number;
+    getZoomScale(): number;
+    rotateLeft(angle: number): void;
+    rotateUp(angle: number): void;
+    getPolarAngle(): number;
+    getAzimuthalAngle(): number;
+    dispose(): void;
+    reset(): void;
+    readonly center: THREE.Vector3;
+    noZoom: boolean;
+}

+ 540 - 0
node_modules/three-orbitcontrols-ts/dist/index.js

@@ -0,0 +1,540 @@
+"use strict";
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var THREE = require("three");
+var STATE = {
+    NONE: -1,
+    ROTATE: 0,
+    DOLLY: 1,
+    PAN: 2,
+    TOUCH_ROTATE: 3,
+    TOUCH_DOLLY: 4,
+    TOUCH_PAN: 5
+};
+var CHANGE_EVENT = { type: 'change' };
+var START_EVENT = { type: 'start' };
+var END_EVENT = { type: 'end' };
+var EPS = 0.000001;
+/**
+* @author qiao / https://github.com/qiao
+* @author mrdoob / http://mrdoob.com
+* @author alteredq / http://alteredqualia.com/
+* @author WestLangley / http://github.com/WestLangley
+* @author erich666 / http://erichaines.com
+* @author nicolaspanel / http://github.com/nicolaspanel
+*
+* This set of controls performs orbiting, dollying (zooming), and panning.
+* Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+*    Orbit - left mouse / touch: one finger move
+*    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+*    Pan - right mouse, or arrow keys / touch: three finger swipe
+*/
+var OrbitControls = (function (_super) {
+    __extends(OrbitControls, _super);
+    function OrbitControls(object, domElement, domWindow) {
+        var _this = _super.call(this) || this;
+        _this.object = object;
+        _this.domElement = (domElement !== undefined) ? domElement : document;
+        _this.window = (domWindow !== undefined) ? domWindow : window;
+        // Set to false to disable this control
+        _this.enabled = true;
+        // "target" sets the location of focus, where the object orbits around
+        _this.target = new THREE.Vector3();
+        // How far you can dolly in and out ( PerspectiveCamera only )
+        _this.minDistance = 0;
+        _this.maxDistance = Infinity;
+        // How far you can zoom in and out ( OrthographicCamera only )
+        _this.minZoom = 0;
+        _this.maxZoom = Infinity;
+        // How far you can orbit vertically, upper and lower limits.
+        // Range is 0 to Math.PI radians.
+        _this.minPolarAngle = 0; // radians
+        _this.maxPolarAngle = Math.PI; // radians
+        // How far you can orbit horizontally, upper and lower limits.
+        // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+        _this.minAzimuthAngle = -Infinity; // radians
+        _this.maxAzimuthAngle = Infinity; // radians
+        // Set to true to enable damping (inertia)
+        // If damping is enabled, you must call controls.update() in your animation loop
+        _this.enableDamping = false;
+        _this.dampingFactor = 0.25;
+        // This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
+        // Set to false to disable zooming
+        _this.enableZoom = true;
+        _this.zoomSpeed = 1.0;
+        // Set to false to disable rotating
+        _this.enableRotate = true;
+        _this.rotateSpeed = 1.0;
+        // Set to false to disable panning
+        _this.enablePan = true;
+        _this.keyPanSpeed = 7.0; // pixels moved per arrow key push
+        // Set to true to automatically rotate around the target
+        // If auto-rotate is enabled, you must call controls.update() in your animation loop
+        _this.autoRotate = false;
+        _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+        // Set to false to disable use of the keys
+        _this.enableKeys = true;
+        // The four arrow keys
+        _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+        // Mouse buttons
+        _this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+        // for reset
+        _this.target0 = _this.target.clone();
+        _this.position0 = _this.object.position.clone();
+        _this.zoom0 = _this.object.zoom;
+        // for update speedup
+        _this.updateOffset = new THREE.Vector3();
+        // so camera.up is the orbit axis
+        _this.updateQuat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));
+        _this.updateQuatInverse = _this.updateQuat.clone().inverse();
+        _this.updateLastPosition = new THREE.Vector3();
+        _this.updateLastQuaternion = new THREE.Quaternion();
+        _this.state = STATE.NONE;
+        _this.scale = 1;
+        // current position in spherical coordinates
+        _this.spherical = new THREE.Spherical();
+        _this.sphericalDelta = new THREE.Spherical();
+        _this.panOffset = new THREE.Vector3();
+        _this.zoomChanged = false;
+        _this.rotateStart = new THREE.Vector2();
+        _this.rotateEnd = new THREE.Vector2();
+        _this.rotateDelta = new THREE.Vector2();
+        _this.panStart = new THREE.Vector2();
+        _this.panEnd = new THREE.Vector2();
+        _this.panDelta = new THREE.Vector2();
+        _this.dollyStart = new THREE.Vector2();
+        _this.dollyEnd = new THREE.Vector2();
+        _this.dollyDelta = new THREE.Vector2();
+        _this.panLeftV = new THREE.Vector3();
+        _this.panUpV = new THREE.Vector3();
+        _this.panInternalOffset = new THREE.Vector3();
+        // event handlers - FSM: listen for events and reset state
+        _this.onMouseDown = function (event) {
+            if (_this.enabled === false)
+                return;
+            event.preventDefault();
+            if (event.button === _this.mouseButtons.ORBIT) {
+                if (_this.enableRotate === false)
+                    return;
+                _this.rotateStart.set(event.clientX, event.clientY);
+                _this.state = STATE.ROTATE;
+            }
+            else if (event.button === _this.mouseButtons.ZOOM) {
+                if (_this.enableZoom === false)
+                    return;
+                _this.dollyStart.set(event.clientX, event.clientY);
+                _this.state = STATE.DOLLY;
+            }
+            else if (event.button === _this.mouseButtons.PAN) {
+                if (_this.enablePan === false)
+                    return;
+                _this.panStart.set(event.clientX, event.clientY);
+                _this.state = STATE.PAN;
+            }
+            if (_this.state !== STATE.NONE) {
+                document.addEventListener('mousemove', _this.onMouseMove, false);
+                document.addEventListener('mouseup', _this.onMouseUp, false);
+                _this.dispatchEvent(START_EVENT);
+            }
+        };
+        _this.onMouseMove = function (event) {
+            if (_this.enabled === false)
+                return;
+            event.preventDefault();
+            if (_this.state === STATE.ROTATE) {
+                if (_this.enableRotate === false)
+                    return;
+                _this.rotateEnd.set(event.clientX, event.clientY);
+                _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart);
+                var element = _this.domElement === document ? _this.domElement.body : _this.domElement;
+                // rotating across whole screen goes 360 degrees around
+                _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed);
+                // rotating up and down along whole screen attempts to go 360, but limited to 180
+                _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed);
+                _this.rotateStart.copy(_this.rotateEnd);
+                _this.update();
+            }
+            else if (_this.state === STATE.DOLLY) {
+                if (_this.enableZoom === false)
+                    return;
+                _this.dollyEnd.set(event.clientX, event.clientY);
+                _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart);
+                if (_this.dollyDelta.y > 0) {
+                    _this.dollyIn(_this.getZoomScale());
+                }
+                else if (_this.dollyDelta.y < 0) {
+                    _this.dollyOut(_this.getZoomScale());
+                }
+                _this.dollyStart.copy(_this.dollyEnd);
+                _this.update();
+            }
+            else if (_this.state === STATE.PAN) {
+                if (_this.enablePan === false)
+                    return;
+                _this.panEnd.set(event.clientX, event.clientY);
+                _this.panDelta.subVectors(_this.panEnd, _this.panStart);
+                _this.pan(_this.panDelta.x, _this.panDelta.y);
+                _this.panStart.copy(_this.panEnd);
+                _this.update();
+            }
+        };
+        _this.onMouseUp = function (event) {
+            if (_this.enabled === false)
+                return;
+            document.removeEventListener('mousemove', _this.onMouseMove, false);
+            document.removeEventListener('mouseup', _this.onMouseUp, false);
+            _this.dispatchEvent(END_EVENT);
+            _this.state = STATE.NONE;
+        };
+        _this.onMouseWheel = function (event) {
+            if (_this.enabled === false || _this.enableZoom === false || (_this.state !== STATE.NONE && _this.state !== STATE.ROTATE))
+                return;
+            event.preventDefault();
+            event.stopPropagation();
+            if (event.deltaY < 0) {
+                _this.dollyOut(_this.getZoomScale());
+            }
+            else if (event.deltaY > 0) {
+                _this.dollyIn(_this.getZoomScale());
+            }
+            _this.update();
+            _this.dispatchEvent(START_EVENT); // not sure why these are here...
+            _this.dispatchEvent(END_EVENT);
+        };
+        _this.onKeyDown = function (event) {
+            if (_this.enabled === false || _this.enableKeys === false || _this.enablePan === false)
+                return;
+            switch (event.keyCode) {
+                case _this.keys.UP:
+                    {
+                        _this.pan(0, _this.keyPanSpeed);
+                        _this.update();
+                    }
+                    break;
+                case _this.keys.BOTTOM:
+                    {
+                        _this.pan(0, -_this.keyPanSpeed);
+                        _this.update();
+                    }
+                    break;
+                case _this.keys.LEFT:
+                    {
+                        _this.pan(_this.keyPanSpeed, 0);
+                        _this.update();
+                    }
+                    break;
+                case _this.keys.RIGHT:
+                    {
+                        _this.pan(-_this.keyPanSpeed, 0);
+                        _this.update();
+                    }
+                    break;
+            }
+        };
+        _this.onTouchStart = function (event) {
+            if (_this.enabled === false)
+                return;
+            switch (event.touches.length) {
+                // one-fingered touch: rotate
+                case 1:
+                    {
+                        if (_this.enableRotate === false)
+                            return;
+                        _this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY);
+                        _this.state = STATE.TOUCH_ROTATE;
+                    }
+                    break;
+                // two-fingered touch: dolly
+                case 2:
+                    {
+                        if (_this.enableZoom === false)
+                            return;
+                        var dx = event.touches[0].pageX - event.touches[1].pageX;
+                        var dy = event.touches[0].pageY - event.touches[1].pageY;
+                        var distance = Math.sqrt(dx * dx + dy * dy);
+                        _this.dollyStart.set(0, distance);
+                        _this.state = STATE.TOUCH_DOLLY;
+                    }
+                    break;
+                // three-fingered touch: pan
+                case 3:
+                    {
+                        if (_this.enablePan === false)
+                            return;
+                        _this.panStart.set(event.touches[0].pageX, event.touches[0].pageY);
+                        _this.state = STATE.TOUCH_PAN;
+                    }
+                    break;
+                default: {
+                    _this.state = STATE.NONE;
+                }
+            }
+            if (_this.state !== STATE.NONE) {
+                _this.dispatchEvent(START_EVENT);
+            }
+        };
+        _this.onTouchMove = function (event) {
+            if (_this.enabled === false)
+                return;
+            event.preventDefault();
+            event.stopPropagation();
+            switch (event.touches.length) {
+                // one-fingered touch: rotate
+                case 1:
+                    {
+                        if (_this.enableRotate === false)
+                            return;
+                        if (_this.state !== STATE.TOUCH_ROTATE)
+                            return; // is this needed?...
+                        _this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);
+                        _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart);
+                        var element = _this.domElement === document ? _this.domElement.body : _this.domElement;
+                        // rotating across whole screen goes 360 degrees around
+                        _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed);
+                        // rotating up and down along whole screen attempts to go 360, but limited to 180
+                        _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed);
+                        _this.rotateStart.copy(_this.rotateEnd);
+                        _this.update();
+                    }
+                    break;
+                // two-fingered touch: dolly
+                case 2:
+                    {
+                        if (_this.enableZoom === false)
+                            return;
+                        if (_this.state !== STATE.TOUCH_DOLLY)
+                            return; // is this needed?...
+                        //console.log( 'handleTouchMoveDolly' );
+                        var dx = event.touches[0].pageX - event.touches[1].pageX;
+                        var dy = event.touches[0].pageY - event.touches[1].pageY;
+                        var distance = Math.sqrt(dx * dx + dy * dy);
+                        _this.dollyEnd.set(0, distance);
+                        _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart);
+                        if (_this.dollyDelta.y > 0) {
+                            _this.dollyOut(_this.getZoomScale());
+                        }
+                        else if (_this.dollyDelta.y < 0) {
+                            _this.dollyIn(_this.getZoomScale());
+                        }
+                        _this.dollyStart.copy(_this.dollyEnd);
+                        _this.update();
+                    }
+                    break;
+                // three-fingered touch: pan
+                case 3:
+                    {
+                        if (_this.enablePan === false)
+                            return;
+                        if (_this.state !== STATE.TOUCH_PAN)
+                            return; // is this needed?...
+                        _this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY);
+                        _this.panDelta.subVectors(_this.panEnd, _this.panStart);
+                        _this.pan(_this.panDelta.x, _this.panDelta.y);
+                        _this.panStart.copy(_this.panEnd);
+                        _this.update();
+                    }
+                    break;
+                default: {
+                    _this.state = STATE.NONE;
+                }
+            }
+        };
+        _this.onTouchEnd = function (event) {
+            if (_this.enabled === false)
+                return;
+            _this.dispatchEvent(END_EVENT);
+            _this.state = STATE.NONE;
+        };
+        _this.onContextMenu = function (event) {
+            event.preventDefault();
+        };
+        _this.domElement.addEventListener('contextmenu', _this.onContextMenu, false);
+        _this.domElement.addEventListener('mousedown', _this.onMouseDown, false);
+        _this.domElement.addEventListener('wheel', _this.onMouseWheel, false);
+        _this.domElement.addEventListener('touchstart', _this.onTouchStart, false);
+        _this.domElement.addEventListener('touchend', _this.onTouchEnd, false);
+        _this.domElement.addEventListener('touchmove', _this.onTouchMove, false);
+        _this.window.addEventListener('keydown', _this.onKeyDown, false);
+        // force an update at start
+        _this.update();
+        return _this;
+    }
+    OrbitControls.prototype.update = function () {
+        var position = this.object.position;
+        this.updateOffset.copy(position).sub(this.target);
+        // rotate offset to "y-axis-is-up" space
+        this.updateOffset.applyQuaternion(this.updateQuat);
+        // angle from z-axis around y-axis
+        this.spherical.setFromVector3(this.updateOffset);
+        if (this.autoRotate && this.state === STATE.NONE) {
+            this.rotateLeft(this.getAutoRotationAngle());
+        }
+        this.spherical.theta += this.sphericalDelta.theta;
+        this.spherical.phi += this.sphericalDelta.phi;
+        // restrict theta to be between desired limits
+        this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta));
+        // restrict phi to be between desired limits
+        this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi));
+        this.spherical.makeSafe();
+        this.spherical.radius *= this.scale;
+        // restrict radius to be between desired limits
+        this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius));
+        // move target to panned location
+        this.target.add(this.panOffset);
+        this.updateOffset.setFromSpherical(this.spherical);
+        // rotate offset back to "camera-up-vector-is-up" space
+        this.updateOffset.applyQuaternion(this.updateQuatInverse);
+        position.copy(this.target).add(this.updateOffset);
+        this.object.lookAt(this.target);
+        if (this.enableDamping === true) {
+            this.sphericalDelta.theta *= (1 - this.dampingFactor);
+            this.sphericalDelta.phi *= (1 - this.dampingFactor);
+        }
+        else {
+            this.sphericalDelta.set(0, 0, 0);
+        }
+        this.scale = 1;
+        this.panOffset.set(0, 0, 0);
+        // update condition is:
+        // min(camera displacement, camera rotation in radians)^2 > EPS
+        // using small-angle approximation cos(x/2) = 1 - x^2 / 8
+        if (this.zoomChanged ||
+            this.updateLastPosition.distanceToSquared(this.object.position) > EPS ||
+            8 * (1 - this.updateLastQuaternion.dot(this.object.quaternion)) > EPS) {
+            this.dispatchEvent(CHANGE_EVENT);
+            this.updateLastPosition.copy(this.object.position);
+            this.updateLastQuaternion.copy(this.object.quaternion);
+            this.zoomChanged = false;
+            return true;
+        }
+        return false;
+    };
+    OrbitControls.prototype.panLeft = function (distance, objectMatrix) {
+        this.panLeftV.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix
+        this.panLeftV.multiplyScalar(-distance);
+        this.panOffset.add(this.panLeftV);
+    };
+    OrbitControls.prototype.panUp = function (distance, objectMatrix) {
+        this.panUpV.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix
+        this.panUpV.multiplyScalar(distance);
+        this.panOffset.add(this.panUpV);
+    };
+    // deltaX and deltaY are in pixels; right and down are positive
+    OrbitControls.prototype.pan = function (deltaX, deltaY) {
+        var element = this.domElement === document ? this.domElement.body : this.domElement;
+        if (this.object instanceof THREE.PerspectiveCamera) {
+            // perspective
+            var position = this.object.position;
+            this.panInternalOffset.copy(position).sub(this.target);
+            var targetDistance = this.panInternalOffset.length();
+            // half of the fov is center to top of screen
+            targetDistance *= Math.tan((this.object.fov / 2) * Math.PI / 180.0);
+            // we actually don't use screenWidth, since perspective camera is fixed to screen height
+            this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix);
+            this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix);
+        }
+        else if (this.object instanceof THREE.OrthographicCamera) {
+            // orthographic
+            this.panLeft(deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth, this.object.matrix);
+            this.panUp(deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight, this.object.matrix);
+        }
+        else {
+            // camera neither orthographic nor perspective
+            console.warn('WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.');
+            this.enablePan = false;
+        }
+    };
+    OrbitControls.prototype.dollyIn = function (dollyScale) {
+        if (this.object instanceof THREE.PerspectiveCamera) {
+            this.scale /= dollyScale;
+        }
+        else if (this.object instanceof THREE.OrthographicCamera) {
+            this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale));
+            this.object.updateProjectionMatrix();
+            this.zoomChanged = true;
+        }
+        else {
+            console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
+            this.enableZoom = false;
+        }
+    };
+    OrbitControls.prototype.dollyOut = function (dollyScale) {
+        if (this.object instanceof THREE.PerspectiveCamera) {
+            this.scale *= dollyScale;
+        }
+        else if (this.object instanceof THREE.OrthographicCamera) {
+            this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale));
+            this.object.updateProjectionMatrix();
+            this.zoomChanged = true;
+        }
+        else {
+            console.warn('WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.');
+            this.enableZoom = false;
+        }
+    };
+    OrbitControls.prototype.getAutoRotationAngle = function () {
+        return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed;
+    };
+    OrbitControls.prototype.getZoomScale = function () {
+        return Math.pow(0.95, this.zoomSpeed);
+    };
+    OrbitControls.prototype.rotateLeft = function (angle) {
+        this.sphericalDelta.theta -= angle;
+    };
+    OrbitControls.prototype.rotateUp = function (angle) {
+        this.sphericalDelta.phi -= angle;
+    };
+    OrbitControls.prototype.getPolarAngle = function () {
+        return this.spherical.phi;
+    };
+    OrbitControls.prototype.getAzimuthalAngle = function () {
+        return this.spherical.theta;
+    };
+    OrbitControls.prototype.dispose = function () {
+        this.domElement.removeEventListener('contextmenu', this.onContextMenu, false);
+        this.domElement.removeEventListener('mousedown', this.onMouseDown, false);
+        this.domElement.removeEventListener('wheel', this.onMouseWheel, false);
+        this.domElement.removeEventListener('touchstart', this.onTouchStart, false);
+        this.domElement.removeEventListener('touchend', this.onTouchEnd, false);
+        this.domElement.removeEventListener('touchmove', this.onTouchMove, false);
+        document.removeEventListener('mousemove', this.onMouseMove, false);
+        document.removeEventListener('mouseup', this.onMouseUp, false);
+        this.window.removeEventListener('keydown', this.onKeyDown, false);
+        //this.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+    };
+    OrbitControls.prototype.reset = function () {
+        this.target.copy(this.target0);
+        this.object.position.copy(this.position0);
+        this.object.zoom = this.zoom0;
+        this.object.updateProjectionMatrix();
+        this.dispatchEvent(CHANGE_EVENT);
+        this.update();
+        this.state = STATE.NONE;
+    };
+    Object.defineProperty(OrbitControls.prototype, "center", {
+        // backward compatibility
+        get: function () {
+            console.warn('THREE.OrbitControls: .center has been renamed to .target');
+            return this.target;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    Object.defineProperty(OrbitControls.prototype, "noZoom", {
+        get: function () {
+            console.warn('THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
+            return !this.enableZoom;
+        },
+        set: function (value) {
+            console.warn('THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.');
+            this.enableZoom = !value;
+        },
+        enumerable: true,
+        configurable: true
+    });
+    return OrbitControls;
+}(THREE.EventDispatcher));
+exports.OrbitControls = OrbitControls;

+ 3 - 0
node_modules/three-orbitcontrols-ts/mocha.opts

@@ -0,0 +1,3 @@
+--require ts-node/register
+--watch-extensions ts
+test/**/*.spec.ts

+ 21 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/LICENSE

@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright © 2010-2016 three.js authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4996 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/build/three.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 349 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/build/three.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4990 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/build/three.module.js


+ 13 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/LICENSE

@@ -0,0 +1,13 @@
+Copyright © 2004 by MAGENTA Ltd. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
+
+The above copyright and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word "MgOpen", or if the modifications are accepted for inclusion in the Font Software itself by the each appointed Administrator.
+
+This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "MgOpen" name.
+
+The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL MAGENTA OR PERSONS OR BODIES IN CHARGE OF ADMINISTRATION AND MAINTENANCE OF THE FONT SOFTWARE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 

+ 2 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/README

@@ -0,0 +1,2 @@
+Use Facetype.js to generate typeface.json fonts.
+http://gero3.github.io/facetype.js/

+ 190 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/NOTICE

@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+

+ 18 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/README.txt

@@ -0,0 +1,18 @@
+Copyright (C) 2008 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+  
+     http://www.apache.org/licenses/LICENSE-2.0
+  
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+##########
+
+This directory contains the fonts for the platform. They are licensed
+under the Apache 2 license.

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_bold.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_mono_regular.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_sans_regular.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_serif_bold.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/droid/droid_serif_regular.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/gentilis_bold.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/gentilis_regular.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/helvetiker_bold.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/helvetiker_regular.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/optimer_bold.typeface.json


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/optimer_regular.typeface.json


BIN
node_modules/three-orbitcontrols-ts/node_modules/three/examples/fonts/ttf/kenpixel.ttf


+ 115 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/AnimationClipCreator.js

@@ -0,0 +1,115 @@
+/**
+ *
+ * Creator of typical test AnimationClips / KeyframeTracks
+ *
+ * @author Ben Houston / http://clara.io/
+ * @author David Sarno / http://lighthaus.us/
+ */
+
+THREE.AnimationClipCreator = function() {
+};
+
+THREE.AnimationClipCreator.CreateRotationAnimation = function( period, axis ) {
+
+	var times = [ 0, period ], values = [ 0, 360 ];
+
+	axis = axis || 'x';
+	var trackName = '.rotation[' + axis + ']';
+
+	var track = new THREE.NumberKeyframeTrack( trackName, times, values );
+
+	return new THREE.AnimationClip( null, period, [ track ] );
+
+};
+
+THREE.AnimationClipCreator.CreateScaleAxisAnimation = function( period, axis ) {
+
+	var times = [ 0, period ], values = [ 0, 1 ];
+
+	axis = axis || 'x';
+	var trackName = '.scale[' + axis + ']';
+
+	var track = new THREE.NumberKeyframeTrack( trackName, times, values );
+
+	return new THREE.AnimationClip( null, period, [ track ] );
+
+};
+
+THREE.AnimationClipCreator.CreateShakeAnimation = function( duration, shakeScale ) {
+
+	var times = [], values = [], tmp = new THREE.Vector3();
+
+	for( var i = 0; i < duration * 10; i ++ ) {
+
+		times.push( i / 10 );
+
+		tmp.set( Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0, Math.random() * 2.0 - 1.0 ).
+			multiply( shakeScale ).
+			toArray( values, values.length );
+
+	}
+
+	var trackName = '.position';
+
+	var track = new THREE.VectorKeyframeTrack( trackName, times, values );
+
+	return new THREE.AnimationClip( null, duration, [ track ] );
+
+};
+
+
+THREE.AnimationClipCreator.CreatePulsationAnimation = function( duration, pulseScale ) {
+
+	var times = [], values = [], tmp = new THREE.Vector3();
+
+	for( var i = 0; i < duration * 10; i ++ ) {
+
+		times.push( i / 10 );
+
+		var scaleFactor = Math.random() * pulseScale;
+		tmp.set( scaleFactor, scaleFactor, scaleFactor ).
+			toArray( values, values.length );
+
+	}
+
+	var trackName = '.scale';
+
+	var track = new THREE.VectorKeyframeTrack( trackName, keys );
+
+	return new THREE.AnimationClip( null, duration, [ track ] );
+
+};
+
+
+THREE.AnimationClipCreator.CreateVisibilityAnimation = function( duration ) {
+
+	var times = [ 0, duration / 2, duration ], values = [ true, false, true ];
+
+	var trackName = '.visible';
+
+	var track = new THREE.BooleanKeyframeTrack( trackName, times, values );
+
+	return new THREE.AnimationClip( null, duration, [ track ] );
+
+};
+
+
+THREE.AnimationClipCreator.CreateMaterialColorAnimation = function( duration, colors, loop ) {
+
+	var times = [], values = [],
+		timeStep = duration / colors.length;
+
+	for( var i = 0; i <= colors.length; i ++ ) {
+
+		timees.push( i * timeStep );
+		values.push( colors[ i % colors.length ] );
+
+	}
+
+	var trackName = '.material[0].color';
+
+	var track = new THREE.ColorKeyframeTrack( trackName, times, values );
+
+	return new THREE.AnimationClip( null, duration, [ track ] );
+
+};

+ 182 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BlendCharacter.js

@@ -0,0 +1,182 @@
+/**
+ * @author Michael Guerrero / http://realitymeltdown.com
+ */
+
+THREE.BlendCharacter = function () {
+
+	this.weightSchedule = [];
+	this.warpSchedule = [];
+
+	this.load = function ( url, onLoad ) {
+
+		var scope = this;
+
+		var loader = new THREE.ObjectLoader();
+		loader.load( url, function( loadedObject ) {
+
+			// The exporter does not currently allow exporting a skinned mesh by itself
+			// so we must fish it out of the hierarchy it is embedded in (scene)
+			loadedObject.traverse( function( object ) {
+
+				if ( object instanceof THREE.SkinnedMesh ) {
+
+					scope.skinnedMesh = object;
+
+				}
+
+			} );
+
+			THREE.SkinnedMesh.call( scope, scope.skinnedMesh.geometry, scope.skinnedMesh.material );
+
+			// If we didn't successfully find the mesh, bail out
+			if ( scope.skinnedMesh == undefined ) {
+
+				console.log( 'unable to find skinned mesh in ' + url );
+				return;
+
+			}
+
+			scope.material.skinning = true;
+
+			scope.mixer = new THREE.AnimationMixer( scope );
+
+			// Create the animations
+			for ( var i = 0; i < scope.geometry.animations.length; ++ i ) {
+
+				scope.mixer.clipAction( scope.geometry.animations[ i ] );
+
+			}
+
+			// Loading is complete, fire the callback
+			if ( onLoad !== undefined ) onLoad();
+
+		} );
+
+	};
+
+	this.loadJSON = function ( url, onLoad ) {
+
+		var scope = this;
+
+		var loader = new THREE.JSONLoader();
+		loader.load( url, function( geometry, materials ) {
+
+			var originalMaterial = materials[ 0 ];
+			originalMaterial.skinning = true;
+
+			THREE.SkinnedMesh.call( scope, geometry, originalMaterial );
+
+			var mixer = new THREE.AnimationMixer( scope );
+			scope.mixer = mixer;
+
+			// Create the animations
+			for ( var i = 0; i < geometry.animations.length; ++ i ) {
+
+				mixer.clipAction( geometry.animations[ i ] );
+
+			}
+
+			// Loading is complete, fire the callback
+			if ( onLoad !== undefined ) onLoad();
+
+		} );
+
+	};
+	
+	this.update = function( dt ) {
+
+		this.mixer.update( dt );
+
+	};
+
+	this.play = function( animName, weight ) {
+
+		//console.log("play('%s', %f)", animName, weight);
+		return this.mixer.clipAction( animName ).
+				setEffectiveWeight( weight ).play();
+	};
+
+	this.crossfade = function( fromAnimName, toAnimName, duration ) {
+
+		this.mixer.stopAllAction();
+
+		var fromAction = this.play( fromAnimName, 1 );
+		var toAction = this.play( toAnimName, 1 );
+
+		fromAction.crossFadeTo( toAction, duration, false );
+
+	};
+
+	this.warp = function( fromAnimName, toAnimName, duration ) {
+
+		this.mixer.stopAllAction();
+
+		var fromAction = this.play( fromAnimName, 1 );
+		var toAction = this.play( toAnimName, 1 );
+
+		fromAction.crossFadeTo( toAction, duration, true );
+
+	};
+
+	this.applyWeight = function( animName, weight ) {
+
+		this.mixer.clipAction( animName ).setEffectiveWeight( weight );
+
+	};
+
+	this.getWeight = function( animName ) {
+
+		return this.mixer.clipAction( animName ).getEffectiveWeight();
+
+	};
+
+	this.pauseAll = function() {
+
+		this.mixer.timeScale = 0;
+
+	};
+
+	this.unPauseAll = function() {
+
+		this.mixer.timeScale = 1;
+
+	};
+
+
+	this.stopAll = function() {
+
+		this.mixer.stopAllAction();
+
+	};
+
+	this.showModel = function( boolean ) {
+
+		this.visible = boolean;
+
+	};
+
+};
+
+
+THREE.BlendCharacter.prototype = Object.create( THREE.SkinnedMesh.prototype );
+THREE.BlendCharacter.prototype.constructor = THREE.BlendCharacter;
+
+THREE.BlendCharacter.prototype.getForward = function() {
+
+	var forward = new THREE.Vector3();
+
+	return function() {
+
+		// pull the character's forward basis vector out of the matrix
+		forward.set(
+			- this.matrix.elements[ 8 ],
+			- this.matrix.elements[ 9 ],
+			- this.matrix.elements[ 10 ]
+		);
+
+		return forward;
+
+	}
+
+};
+

+ 207 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BlendCharacterGui.js

@@ -0,0 +1,207 @@
+/**
+ * @author Michael Guerrero / http://realitymeltdown.com
+ */
+
+function BlendCharacterGui( blendMesh ) {
+
+	var controls = {
+
+		gui: null,
+		"Show Model": true,
+		"Show Skeleton": false,
+		"Time Scale": 1.0,
+		"Step Size": 0.016,
+		"Crossfade Time": 3.5,
+		"idle": 0.33,
+		"walk": 0.33,
+		"run": 0.33
+
+	};
+
+	var blendMesh = blendMesh;
+
+	this.showModel = function() {
+
+		return controls[ 'Show Model' ];
+
+	};
+
+	this.showSkeleton = function() {
+
+		return controls[ 'Show Skeleton' ];
+
+	};
+
+	this.getTimeScale = function() {
+
+		return controls[ 'Time Scale' ];
+
+	};
+
+	this.update = function( time ) {
+
+		controls[ 'idle' ] = blendMesh.getWeight( 'idle' );
+		controls[ 'walk' ] = blendMesh.getWeight( 'walk' );
+		controls[ 'run' ] = blendMesh.getWeight( 'run' );
+
+	};
+
+	var init = function() {
+
+		controls.gui = new dat.GUI();
+
+		var settings = controls.gui.addFolder( 'Settings' );
+		var playback = controls.gui.addFolder( 'Playback' );
+		var blending = controls.gui.addFolder( 'Blend Tuning' );
+
+		settings.add( controls, "Show Model" ).onChange( controls.showModelChanged );
+		settings.add( controls, "Show Skeleton" ).onChange( controls.showSkeletonChanged );
+		settings.add( controls, "Time Scale", 0, 1, 0.01 );
+		settings.add( controls, "Step Size", 0.01, 0.1, 0.01 );
+		settings.add( controls, "Crossfade Time", 0.1, 6.0, 0.05 );
+
+		// These controls execute functions
+		playback.add( controls, "start" );
+		playback.add( controls, "pause" );
+		playback.add( controls, "step" );
+		playback.add( controls, "idle to walk" );
+		playback.add( controls, "walk to run" );
+		playback.add( controls, "warp walk to run" );
+
+		blending.add( controls, "idle", 0, 1, 0.01 ).listen().onChange( controls.weight );
+		blending.add( controls, "walk", 0, 1, 0.01 ).listen().onChange( controls.weight );
+		blending.add( controls, "run", 0, 1, 0.01 ).listen().onChange( controls.weight );
+
+		settings.open();
+		playback.open();
+		blending.open();
+
+	};
+
+	var getAnimationData = function() {
+
+		return {
+
+			detail: {
+
+				anims: [ "idle", "walk", "run" ],
+
+				weights: [ controls[ 'idle' ],
+						   controls[ 'walk' ],
+						   controls[ 'run' ] ]
+			}
+
+		};
+
+	};
+
+	controls.start = function() {
+
+		var startEvent = new CustomEvent( 'start-animation', getAnimationData() );
+		window.dispatchEvent( startEvent );
+
+	};
+
+	controls.stop = function() {
+
+		var stopEvent = new CustomEvent( 'stop-animation' );
+		window.dispatchEvent( stopEvent );
+
+	};
+
+	controls.pause = function() {
+
+		var pauseEvent = new CustomEvent( 'pause-animation' );
+		window.dispatchEvent( pauseEvent );
+
+	};
+
+	controls.step = function() {
+
+		var stepData = { detail: { stepSize: controls[ 'Step Size' ] } };
+		window.dispatchEvent( new CustomEvent( 'step-animation', stepData ) );
+
+	};
+
+	controls.weight = function() {
+
+		// renormalize
+		var sum = controls[ 'idle' ] + controls[ 'walk' ] + controls[ 'run' ];
+		controls[ 'idle' ] /= sum;
+		controls[ 'walk' ] /= sum;
+		controls[ 'run' ] /= sum;
+
+		var weightEvent = new CustomEvent( 'weight-animation', getAnimationData() );
+		window.dispatchEvent( weightEvent );
+
+	};
+
+	controls.crossfade = function( from, to ) {
+
+		var fadeData = getAnimationData();
+		fadeData.detail.from = from;
+		fadeData.detail.to = to;
+		fadeData.detail.time = controls[ "Crossfade Time" ];
+
+		window.dispatchEvent( new CustomEvent( 'crossfade', fadeData ) );
+
+	};
+
+	controls.warp = function( from, to ) {
+
+		var warpData = getAnimationData();
+		warpData.detail.from = 'walk';
+		warpData.detail.to = 'run';
+		warpData.detail.time = controls[ "Crossfade Time" ];
+
+		window.dispatchEvent( new CustomEvent( 'warp', warpData ) );
+
+	};
+
+	controls[ 'idle to walk' ] = function() {
+
+		controls.crossfade( 'idle', 'walk' );
+
+	};
+
+	controls[ 'walk to run' ] = function() {
+
+		controls.crossfade( 'walk', 'run' );
+
+	};
+
+	controls[ 'warp walk to run' ] = function() {
+
+		controls.warp( 'walk', 'run' );
+
+	};
+
+	controls.showSkeletonChanged = function() {
+
+		var data = {
+			detail: {
+				shouldShow: controls[ 'Show Skeleton' ]
+			}
+		};
+
+		window.dispatchEvent( new CustomEvent( 'toggle-show-skeleton', data ) );
+
+	};
+
+
+	controls.showModelChanged = function() {
+
+		var data = {
+			detail: {
+				shouldShow: controls[ 'Show Model' ]
+			}
+		};
+
+		window.dispatchEvent( new CustomEvent( 'toggle-show-model', data ) );
+
+	};
+
+
+	init.call( this );
+
+}

+ 187 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/BufferGeometryUtils.js

@@ -0,0 +1,187 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.BufferGeometryUtils = {
+
+	computeTangents: function ( geometry ) {
+
+		var index = geometry.index;
+		var attributes = geometry.attributes;
+
+		// based on http://www.terathon.com/code/tangent.html
+		// (per vertex tangents)
+
+		if ( index === null ||
+			 attributes.position === undefined ||
+			 attributes.normal === undefined ||
+			 attributes.uv === undefined ) {
+
+			console.warn( 'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
+			return;
+
+		}
+
+		var indices = index.array;
+		var positions = attributes.position.array;
+		var normals = attributes.normal.array;
+		var uvs = attributes.uv.array;
+
+		var nVertices = positions.length / 3;
+
+		if ( attributes.tangent === undefined ) {
+
+			geometry.addAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
+
+		}
+
+		var tangents = attributes.tangent.array;
+
+		var tan1 = [], tan2 = [];
+
+		for ( var k = 0; k < nVertices; k ++ ) {
+
+			tan1[ k ] = new THREE.Vector3();
+			tan2[ k ] = new THREE.Vector3();
+
+		}
+
+		var vA = new THREE.Vector3(),
+			vB = new THREE.Vector3(),
+			vC = new THREE.Vector3(),
+
+			uvA = new THREE.Vector2(),
+			uvB = new THREE.Vector2(),
+			uvC = new THREE.Vector2(),
+
+			sdir = new THREE.Vector3(),
+			tdir = new THREE.Vector3();
+
+		function handleTriangle( a, b, c ) {
+
+			vA.fromArray( positions, a * 3 );
+			vB.fromArray( positions, b * 3 );
+			vC.fromArray( positions, c * 3 );
+
+			uvA.fromArray( uvs, a * 2 );
+			uvB.fromArray( uvs, b * 2 );
+			uvC.fromArray( uvs, c * 2 );
+
+			var x1 = vB.x - vA.x;
+			var x2 = vC.x - vA.x;
+
+			var y1 = vB.y - vA.y;
+			var y2 = vC.y - vA.y;
+
+			var z1 = vB.z - vA.z;
+			var z2 = vC.z - vA.z;
+
+			var s1 = uvB.x - uvA.x;
+			var s2 = uvC.x - uvA.x;
+
+			var t1 = uvB.y - uvA.y;
+			var t2 = uvC.y - uvA.y;
+
+			var r = 1.0 / ( s1 * t2 - s2 * t1 );
+
+			sdir.set(
+				( t2 * x1 - t1 * x2 ) * r,
+				( t2 * y1 - t1 * y2 ) * r,
+				( t2 * z1 - t1 * z2 ) * r
+			);
+
+			tdir.set(
+				( s1 * x2 - s2 * x1 ) * r,
+				( s1 * y2 - s2 * y1 ) * r,
+				( s1 * z2 - s2 * z1 ) * r
+			);
+
+			tan1[ a ].add( sdir );
+			tan1[ b ].add( sdir );
+			tan1[ c ].add( sdir );
+
+			tan2[ a ].add( tdir );
+			tan2[ b ].add( tdir );
+			tan2[ c ].add( tdir );
+
+		}
+
+		var groups = geometry.groups;
+
+		if ( groups.length === 0 ) {
+
+			groups = [ {
+				start: 0,
+				count: indices.length
+			} ];
+
+		}
+
+		for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
+
+			var group = groups[ j ];
+
+			var start = group.start;
+			var count = group.count;
+
+			for ( var i = start, il = start + count; i < il; i += 3 ) {
+
+				handleTriangle(
+					indices[ i + 0 ],
+					indices[ i + 1 ],
+					indices[ i + 2 ]
+				);
+
+			}
+
+		}
+
+		var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
+		var n = new THREE.Vector3(), n2 = new THREE.Vector3();
+		var w, t, test;
+
+		function handleVertex( v ) {
+
+			n.fromArray( normals, v * 3 );
+			n2.copy( n );
+
+			t = tan1[ v ];
+
+			// Gram-Schmidt orthogonalize
+
+			tmp.copy( t );
+			tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
+
+			// Calculate handedness
+
+			tmp2.crossVectors( n2, t );
+			test = tmp2.dot( tan2[ v ] );
+			w = ( test < 0.0 ) ? - 1.0 : 1.0;
+
+			tangents[ v * 4 ] = tmp.x;
+			tangents[ v * 4 + 1 ] = tmp.y;
+			tangents[ v * 4 + 2 ] = tmp.z;
+			tangents[ v * 4 + 3 ] = w;
+
+		}
+
+		for ( var j = 0, jl = groups.length; j < jl; ++ j ) {
+
+			var group = groups[ j ];
+
+			var start = group.start;
+			var count = group.count;
+
+			for ( var i = start, il = start + count; i < il; i += 3 ) {
+
+				handleVertex( indices[ i + 0 ] );
+				handleVertex( indices[ i + 1 ] );
+				handleVertex( indices[ i + 2 ] );
+
+			}
+
+		}
+
+	}
+
+};

+ 407 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Car.js

@@ -0,0 +1,407 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Car = function () {
+
+	var scope = this;
+
+	// car geometry manual parameters
+
+	this.modelScale = 1;
+
+	this.backWheelOffset = 2;
+
+	this.autoWheelGeometry = true;
+
+	// car geometry parameters automatically set from wheel mesh
+	// 	- assumes wheel mesh is front left wheel in proper global
+	//    position with respect to body mesh
+	//	- other wheels are mirrored against car root
+	//	- if necessary back wheels can be offset manually
+
+	this.wheelOffset = new THREE.Vector3();
+
+	this.wheelDiameter = 1;
+
+	// car "feel" parameters
+
+	this.MAX_SPEED = 2200;
+	this.MAX_REVERSE_SPEED = - 1500;
+
+	this.MAX_WHEEL_ROTATION = 0.6;
+
+	this.FRONT_ACCELERATION = 1250;
+	this.BACK_ACCELERATION = 1500;
+
+	this.WHEEL_ANGULAR_ACCELERATION = 1.5;
+
+	this.FRONT_DECCELERATION = 750;
+	this.WHEEL_ANGULAR_DECCELERATION = 1.0;
+
+	this.STEERING_RADIUS_RATIO = 0.0023;
+
+	this.MAX_TILT_SIDES = 0.05;
+	this.MAX_TILT_FRONTBACK = 0.015;
+
+	// internal control variables
+
+	this.speed = 0;
+	this.acceleration = 0;
+
+	this.wheelOrientation = 0;
+	this.carOrientation = 0;
+
+	// car rigging
+
+	this.root = new THREE.Object3D();
+
+	this.frontLeftWheelRoot = new THREE.Object3D();
+	this.frontRightWheelRoot = new THREE.Object3D();
+
+	this.bodyMesh = null;
+
+	this.frontLeftWheelMesh = null;
+	this.frontRightWheelMesh = null;
+
+	this.backLeftWheelMesh = null;
+	this.backRightWheelMesh = null;
+
+	this.bodyGeometry = null;
+	this.wheelGeometry = null;
+
+	this.bodyMaterials = null;
+	this.wheelMaterials = null;
+
+	// internal helper variables
+
+	this.loaded = false;
+
+	this.meshes = [];
+
+	// API
+
+	this.enableShadows = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].castShadow = enable;
+			this.meshes[ i ].receiveShadow = enable;
+
+		}
+
+	};
+
+	this.setVisible = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].visible = enable;
+			this.meshes[ i ].visible = enable;
+
+		}
+
+	};
+
+	this.loadPartsJSON = function ( bodyURL, wheelURL ) {
+
+		var loader = new THREE.JSONLoader();
+
+		loader.load( bodyURL, function( geometry, materials ) {
+
+			createBody( geometry, materials )
+
+		} );
+		loader.load( wheelURL, function( geometry, materials ) {
+
+			createWheels( geometry, materials )
+
+		} );
+
+	};
+
+	this.loadPartsBinary = function ( bodyURL, wheelURL ) {
+
+		var loader = new THREE.BinaryLoader();
+
+		loader.load( bodyURL, function( geometry, materials ) {
+
+			createBody( geometry, materials )
+
+		} );
+		loader.load( wheelURL, function( geometry, materials ) {
+
+			createWheels( geometry, materials )
+
+		} );
+
+	};
+
+	this.updateCarModel = function ( delta, controls ) {
+
+		// speed and wheels based on controls
+
+		if ( controls.moveForward ) {
+
+			this.speed = THREE.Math.clamp( this.speed + delta * this.FRONT_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
+			this.acceleration = THREE.Math.clamp( this.acceleration + delta, - 1, 1 );
+
+		}
+
+		if ( controls.moveBackward ) {
+
+
+			this.speed = THREE.Math.clamp( this.speed - delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
+			this.acceleration = THREE.Math.clamp( this.acceleration - delta, - 1, 1 );
+
+		}
+
+		if ( controls.moveLeft ) {
+
+			this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
+
+		}
+
+		if ( controls.moveRight ) {
+
+			this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_ACCELERATION, - this.MAX_WHEEL_ROTATION, this.MAX_WHEEL_ROTATION );
+
+		}
+
+		// speed decay
+
+		if ( ! ( controls.moveForward || controls.moveBackward ) ) {
+
+			if ( this.speed > 0 ) {
+
+				var k = exponentialEaseOut( this.speed / this.MAX_SPEED );
+
+				this.speed = THREE.Math.clamp( this.speed - k * delta * this.FRONT_DECCELERATION, 0, this.MAX_SPEED );
+				this.acceleration = THREE.Math.clamp( this.acceleration - k * delta, 0, 1 );
+
+			} else {
+
+				var k = exponentialEaseOut( this.speed / this.MAX_REVERSE_SPEED );
+
+				this.speed = THREE.Math.clamp( this.speed + k * delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, 0 );
+				this.acceleration = THREE.Math.clamp( this.acceleration + k * delta, - 1, 0 );
+
+			}
+
+
+		}
+
+		// steering decay
+
+		if ( ! ( controls.moveLeft || controls.moveRight ) ) {
+
+			if ( this.wheelOrientation > 0 ) {
+
+				this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation - delta * this.WHEEL_ANGULAR_DECCELERATION, 0, this.MAX_WHEEL_ROTATION );
+
+			} else {
+
+				this.wheelOrientation = THREE.Math.clamp( this.wheelOrientation + delta * this.WHEEL_ANGULAR_DECCELERATION, - this.MAX_WHEEL_ROTATION, 0 );
+
+			}
+
+		}
+
+		// car update
+
+		var forwardDelta = this.speed * delta;
+
+		this.carOrientation += ( forwardDelta * this.STEERING_RADIUS_RATIO ) * this.wheelOrientation;
+
+		// displacement
+
+		this.root.position.x += Math.sin( this.carOrientation ) * forwardDelta;
+		this.root.position.z += Math.cos( this.carOrientation ) * forwardDelta;
+
+		// steering
+
+		this.root.rotation.y = this.carOrientation;
+
+		// tilt
+
+		if ( this.loaded ) {
+
+			this.bodyMesh.rotation.z = this.MAX_TILT_SIDES * this.wheelOrientation * ( this.speed / this.MAX_SPEED );
+			this.bodyMesh.rotation.x = - this.MAX_TILT_FRONTBACK * this.acceleration;
+
+		}
+
+		// wheels rolling
+
+		var angularSpeedRatio = 1 / ( this.modelScale * ( this.wheelDiameter / 2 ) );
+
+		var wheelDelta = forwardDelta * angularSpeedRatio;
+
+		if ( this.loaded ) {
+
+			this.frontLeftWheelMesh.rotation.x += wheelDelta;
+			this.frontRightWheelMesh.rotation.x += wheelDelta;
+			this.backLeftWheelMesh.rotation.x += wheelDelta;
+			this.backRightWheelMesh.rotation.x += wheelDelta;
+
+		}
+
+		// front wheels steering
+
+		this.frontLeftWheelRoot.rotation.y = this.wheelOrientation;
+		this.frontRightWheelRoot.rotation.y = this.wheelOrientation;
+
+	};
+
+	// internal helper methods
+
+	function createBody ( geometry, materials ) {
+
+		scope.bodyGeometry = geometry;
+		scope.bodyMaterials = materials;
+
+		createCar();
+
+	}
+
+	function createWheels ( geometry, materials ) {
+
+		scope.wheelGeometry = geometry;
+		scope.wheelMaterials = materials;
+
+		createCar();
+
+	}
+
+	function createCar () {
+
+		if ( scope.bodyGeometry && scope.wheelGeometry ) {
+
+			// compute wheel geometry parameters
+
+			if ( scope.autoWheelGeometry ) {
+
+				scope.wheelGeometry.computeBoundingBox();
+
+				var bb = scope.wheelGeometry.boundingBox;
+
+				scope.wheelOffset.addVectors( bb.min, bb.max );
+				scope.wheelOffset.multiplyScalar( 0.5 );
+
+				scope.wheelDiameter = bb.max.y - bb.min.y;
+
+				scope.wheelGeometry.center();
+
+			}
+
+			// rig the car
+
+			var s = scope.modelScale,
+				delta = new THREE.Vector3();
+
+			var bodyFaceMaterial = new THREE.MultiMaterial( scope.bodyMaterials );
+			var wheelFaceMaterial = new THREE.MultiMaterial( scope.wheelMaterials );
+
+			// body
+
+			scope.bodyMesh = new THREE.Mesh( scope.bodyGeometry, bodyFaceMaterial );
+			scope.bodyMesh.scale.set( s, s, s );
+
+			scope.root.add( scope.bodyMesh );
+
+			// front left wheel
+
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, s ) );
+
+			scope.frontLeftWheelRoot.position.add( delta );
+
+			scope.frontLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
+			scope.frontLeftWheelMesh.scale.set( s, s, s );
+
+			scope.frontLeftWheelRoot.add( scope.frontLeftWheelMesh );
+			scope.root.add( scope.frontLeftWheelRoot );
+
+			// front right wheel
+
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, s ) );
+
+			scope.frontRightWheelRoot.position.add( delta );
+
+			scope.frontRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
+
+			scope.frontRightWheelMesh.scale.set( s, s, s );
+			scope.frontRightWheelMesh.rotation.z = Math.PI;
+
+			scope.frontRightWheelRoot.add( scope.frontRightWheelMesh );
+			scope.root.add( scope.frontRightWheelRoot );
+
+			// back left wheel
+
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, - s ) );
+			delta.z -= scope.backWheelOffset;
+
+			scope.backLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
+
+			scope.backLeftWheelMesh.position.add( delta );
+			scope.backLeftWheelMesh.scale.set( s, s, s );
+
+			scope.root.add( scope.backLeftWheelMesh );
+
+			// back right wheel
+
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, - s ) );
+			delta.z -= scope.backWheelOffset;
+
+			scope.backRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
+
+			scope.backRightWheelMesh.position.add( delta );
+			scope.backRightWheelMesh.scale.set( s, s, s );
+			scope.backRightWheelMesh.rotation.z = Math.PI;
+
+			scope.root.add( scope.backRightWheelMesh );
+
+			// cache meshes
+
+			scope.meshes = [ scope.bodyMesh, scope.frontLeftWheelMesh, scope.frontRightWheelMesh, scope.backLeftWheelMesh, scope.backRightWheelMesh ];
+
+			// callback
+
+			scope.loaded = true;
+
+			if ( scope.callback ) {
+
+				scope.callback( scope );
+
+			}
+
+		}
+
+	}
+
+	function quadraticEaseOut( k ) {
+
+		return - k * ( k - 2 );
+
+	}
+	function cubicEaseOut( k ) {
+
+		return -- k * k * k + 1;
+
+	}
+	function circularEaseOut( k ) {
+
+		return Math.sqrt( 1 - -- k * k );
+
+	}
+	function sinusoidalEaseOut( k ) {
+
+		return Math.sin( k * Math.PI / 2 );
+
+	}
+	function exponentialEaseOut( k ) {
+
+		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
+
+	}
+
+};

+ 330 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Cloth.js

@@ -0,0 +1,330 @@
+/*
+ * Cloth Simulation using a relaxed constraints solver
+ */
+
+// Suggested Readings
+
+// Advanced Character Physics by Thomas Jakobsen Character
+// http://freespace.virgin.net/hugo.elias/models/m_cloth.htm
+// http://en.wikipedia.org/wiki/Cloth_modeling
+// http://cg.alexandra.dk/tag/spring-mass-system/
+// Real-time Cloth Animation http://www.darwin3d.com/gamedev/articles/col0599.pdf
+
+var DAMPING = 0.03;
+var DRAG = 1 - DAMPING;
+var MASS = 0.1;
+var restDistance = 25;
+
+var xSegs = 10;
+var ySegs = 10;
+
+var clothFunction = plane( restDistance * xSegs, restDistance * ySegs );
+
+var cloth = new Cloth( xSegs, ySegs );
+
+var GRAVITY = 981 * 1.4;
+var gravity = new THREE.Vector3( 0, - GRAVITY, 0 ).multiplyScalar( MASS );
+
+
+var TIMESTEP = 18 / 1000;
+var TIMESTEP_SQ = TIMESTEP * TIMESTEP;
+
+var pins = [];
+
+
+var wind = true;
+var windStrength = 2;
+var windForce = new THREE.Vector3( 0, 0, 0 );
+
+var ballPosition = new THREE.Vector3( 0, - 45, 0 );
+var ballSize = 60; //40
+
+var tmpForce = new THREE.Vector3();
+
+var lastTime;
+
+
+function plane( width, height ) {
+
+	return function( u, v ) {
+
+		var x = ( u - 0.5 ) * width;
+		var y = ( v + 0.5 ) * height;
+		var z = 0;
+
+		return new THREE.Vector3( x, y, z );
+
+	};
+
+}
+
+function Particle( x, y, z, mass ) {
+
+	this.position = clothFunction( x, y ); // position
+	this.previous = clothFunction( x, y ); // previous
+	this.original = clothFunction( x, y );
+	this.a = new THREE.Vector3( 0, 0, 0 ); // acceleration
+	this.mass = mass;
+	this.invMass = 1 / mass;
+	this.tmp = new THREE.Vector3();
+	this.tmp2 = new THREE.Vector3();
+
+}
+
+// Force -> Acceleration
+
+Particle.prototype.addForce = function( force ) {
+
+	this.a.add(
+		this.tmp2.copy( force ).multiplyScalar( this.invMass )
+	);
+
+};
+
+
+// Performs Verlet integration
+
+Particle.prototype.integrate = function( timesq ) {
+
+	var newPos = this.tmp.subVectors( this.position, this.previous );
+	newPos.multiplyScalar( DRAG ).add( this.position );
+	newPos.add( this.a.multiplyScalar( timesq ) );
+
+	this.tmp = this.previous;
+	this.previous = this.position;
+	this.position = newPos;
+
+	this.a.set( 0, 0, 0 );
+
+};
+
+
+var diff = new THREE.Vector3();
+
+function satisifyConstraints( p1, p2, distance ) {
+
+	diff.subVectors( p2.position, p1.position );
+	var currentDist = diff.length();
+	if ( currentDist === 0 ) return; // prevents division by 0
+	var correction = diff.multiplyScalar( 1 - distance / currentDist );
+	var correctionHalf = correction.multiplyScalar( 0.5 );
+	p1.position.add( correctionHalf );
+	p2.position.sub( correctionHalf );
+
+}
+
+
+function Cloth( w, h ) {
+
+	w = w || 10;
+	h = h || 10;
+	this.w = w;
+	this.h = h;
+
+	var particles = [];
+	var constraints = [];
+
+	var u, v;
+
+	// Create particles
+	for ( v = 0; v <= h; v ++ ) {
+
+		for ( u = 0; u <= w; u ++ ) {
+
+			particles.push(
+				new Particle( u / w, v / h, 0, MASS )
+			);
+
+		}
+
+	}
+
+	// Structural
+
+	for ( v = 0; v < h; v ++ ) {
+
+		for ( u = 0; u < w; u ++ ) {
+
+			constraints.push( [
+				particles[ index( u, v ) ],
+				particles[ index( u, v + 1 ) ],
+				restDistance
+			] );
+
+			constraints.push( [
+				particles[ index( u, v ) ],
+				particles[ index( u + 1, v ) ],
+				restDistance
+			] );
+
+		}
+
+	}
+
+	for ( u = w, v = 0; v < h; v ++ ) {
+
+		constraints.push( [
+			particles[ index( u, v ) ],
+			particles[ index( u, v + 1 ) ],
+			restDistance
+
+		] );
+
+	}
+
+	for ( v = h, u = 0; u < w; u ++ ) {
+
+		constraints.push( [
+			particles[ index( u, v ) ],
+			particles[ index( u + 1, v ) ],
+			restDistance
+		] );
+
+	}
+
+
+	// While many systems use shear and bend springs,
+	// the relaxed constraints model seems to be just fine
+	// using structural springs.
+	// Shear
+	// var diagonalDist = Math.sqrt(restDistance * restDistance * 2);
+
+
+	// for (v=0;v<h;v++) {
+	// 	for (u=0;u<w;u++) {
+
+	// 		constraints.push([
+	// 			particles[index(u, v)],
+	// 			particles[index(u+1, v+1)],
+	// 			diagonalDist
+	// 		]);
+
+	// 		constraints.push([
+	// 			particles[index(u+1, v)],
+	// 			particles[index(u, v+1)],
+	// 			diagonalDist
+	// 		]);
+
+	// 	}
+	// }
+
+
+	this.particles = particles;
+	this.constraints = constraints;
+
+	function index( u, v ) {
+
+		return u + v * ( w + 1 );
+
+	}
+
+	this.index = index;
+
+}
+
+function simulate( time ) {
+
+	if ( ! lastTime ) {
+
+		lastTime = time;
+		return;
+
+	}
+
+	var i, il, particles, particle, pt, constraints, constraint;
+
+	// Aerodynamics forces
+
+	if ( wind ) {
+
+		var face, faces = clothGeometry.faces, normal;
+
+		particles = cloth.particles;
+
+		for ( i = 0, il = faces.length; i < il; i ++ ) {
+
+			face = faces[ i ];
+			normal = face.normal;
+
+			tmpForce.copy( normal ).normalize().multiplyScalar( normal.dot( windForce ) );
+			particles[ face.a ].addForce( tmpForce );
+			particles[ face.b ].addForce( tmpForce );
+			particles[ face.c ].addForce( tmpForce );
+
+		}
+
+	}
+
+	for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
+
+		particle = particles[ i ];
+		particle.addForce( gravity );
+
+		particle.integrate( TIMESTEP_SQ );
+
+	}
+
+	// Start Constraints
+
+	constraints = cloth.constraints;
+	il = constraints.length;
+
+	for ( i = 0; i < il; i ++ ) {
+
+		constraint = constraints[ i ];
+		satisifyConstraints( constraint[ 0 ], constraint[ 1 ], constraint[ 2 ] );
+
+	}
+
+	// Ball Constraints
+
+	ballPosition.z = - Math.sin( Date.now() / 600 ) * 90 ; //+ 40;
+	ballPosition.x = Math.cos( Date.now() / 400 ) * 70;
+
+	if ( sphere.visible ) {
+
+		for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
+
+			particle = particles[ i ];
+			pos = particle.position;
+			diff.subVectors( pos, ballPosition );
+			if ( diff.length() < ballSize ) {
+
+				// collided
+				diff.normalize().multiplyScalar( ballSize );
+				pos.copy( ballPosition ).add( diff );
+
+			}
+
+		}
+
+	}
+
+
+	// Floor Constraints
+
+	for ( particles = cloth.particles, i = 0, il = particles.length; i < il; i ++ ) {
+
+		particle = particles[ i ];
+		pos = particle.position;
+		if ( pos.y < - 250 ) {
+
+			pos.y = - 250;
+
+		}
+
+	}
+
+	// Pin Constraints
+
+	for ( i = 0, il = pins.length; i < il; i ++ ) {
+
+		var xy = pins[ i ];
+		var p = particles[ xy ];
+		p.position.copy( p.original );
+		p.previous.copy( p.original );
+
+	}
+
+
+}

+ 489 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ConvexObjectBreaker.js

@@ -0,0 +1,489 @@
+/**
+ * @author yomboprime https://github.com/yomboprime
+ *
+ * @fileoverview This class can be used to subdivide a convex Geometry object into pieces.
+ *
+ * Usage:
+ *
+ * Use the function prepareBreakableObject to prepare a Mesh object to be broken.
+ *
+ * Then, call the various functions to subdivide the object (subdivideByImpact, cutByPlane)
+ *
+ * Sub-objects that are product of subdivision don't need prepareBreakableObject to be called on them.
+ *
+ * Requisites for the object:
+ *
+ *  - Mesh object must have a Geometry (not BufferGeometry) and a Material
+ *
+ *  - The Geometry must be convex (this is not tested in the library). You can create convex
+ *  Geometries with THREE.ConvexGeometry. The BoxGeometry, SphereGeometry and other convex primitives
+ *  can also be used.
+ *
+ * Note: This lib adds member variables to object's userData member and to its vertices.
+ * (see prepareBreakableObject function)
+ * Use with caution and read the code when using with other libs.
+ *
+ * @param {double} minSizeForBreak Min size a debris can have to break.
+ * @param {double} smallDelta Max distance to consider that a point belongs to a plane.
+ * 
+  */
+
+THREE.ConvexObjectBreaker = function( minSizeForBreak, smallDelta ) {
+
+	this.minSizeForBreak = minSizeForBreak || 1.4;
+	this.smallDelta = smallDelta || 0.0001;
+
+	this.tempLine1 = new THREE.Line3();
+	this.tempPlane1 = new THREE.Plane();
+	this.tempPlane2 = new THREE.Plane();
+	this.tempCM1 = new THREE.Vector3();
+	this.tempCM2 = new THREE.Vector3();
+	this.tempVector3 = new THREE.Vector3();
+	this.tempVector3_2 = new THREE.Vector3();
+	this.tempVector3_3 = new THREE.Vector3();
+	this.tempResultObjects = { object1: null, object2: null };
+
+	this.segments = [];
+	var n = 30 * 30;
+	for ( var i = 0; i < n; i++ ) {
+		this.segments[ i ] = false;
+	}
+
+};
+
+THREE.ConvexObjectBreaker.prototype = {
+
+	constructor: THREE.ConvexObjectBreaker,
+
+	prepareBreakableObject: function( object, mass, velocity, angularVelocity, breakable ) {
+
+		// object is a THREE.Object3d (normally a Mesh), must have a Geometry, and it must be convex.
+		// Its material property is propagated to its children (sub-pieces)
+		// mass must be > 0
+
+		// Create vertices mark
+		var vertices = object.geometry.vertices;
+		for ( var i = 0, il = vertices.length; i < il; i++ ) {
+			vertices[ i ].mark = 0;
+		}
+
+		var userData = object.userData;
+		userData.mass = mass;
+		userData.velocity = velocity.clone();
+		userData.angularVelocity = angularVelocity.clone();
+		userData.breakable = breakable;
+
+	},
+
+	/*
+	 * @param {int} maxRadialIterations Iterations for radial cuts.
+	 * @param {int} maxRandomIterations Max random iterations for not-radial cuts
+	 * @param {double} minSizeForRadialSubdivision Min size a debris can have to break in radial subdivision.
+	 *
+	 * Returns the array of pieces
+	 */
+	subdivideByImpact: function( object, pointOfImpact, normal, maxRadialIterations, maxRandomIterations, minSizeForRadialSubdivision ) {
+
+		var debris = [];
+
+		var tempPlane1 = this.tempPlane1;
+		var tempPlane2 = this.tempPlane2;
+
+		this.tempVector3.addVectors( pointOfImpact, normal );
+		tempPlane1.setFromCoplanarPoints( pointOfImpact, object.position, this.tempVector3 );
+
+		var maxTotalIterations = maxRandomIterations + maxRadialIterations;
+
+		var scope = this;
+
+		function subdivideRadial( subObject, startAngle, endAngle, numIterations ) {
+
+			if ( Math.random() < numIterations * 0.05 || numIterations > maxTotalIterations ) {
+
+				debris.push( subObject );
+
+				return;
+				
+			}
+			
+			var angle = Math.PI;
+
+			if ( numIterations === 0 ) {
+
+				tempPlane2.normal.copy( tempPlane1.normal );
+				tempPlane2.constant = tempPlane1.constant;
+
+			}
+			else {
+
+				if ( numIterations <= maxRadialIterations ) {
+					
+					angle = ( endAngle - startAngle ) * ( 0.2 + 0.6 * Math.random() ) + startAngle;
+
+					// Rotate tempPlane2 at impact point around normal axis and the angle
+					scope.tempVector3_2.copy( object.position ).sub( pointOfImpact ).applyAxisAngle( normal, angle ).add( pointOfImpact );
+					tempPlane2.setFromCoplanarPoints( pointOfImpact, scope.tempVector3, scope.tempVector3_2 );
+
+				}
+				else {
+
+					angle = ( ( 0.5 * ( numIterations & 1 ) ) + 0.2 * ( 2 - Math.random() ) ) * Math.PI;
+
+					// Rotate tempPlane2 at object position around normal axis and the angle
+					scope.tempVector3_2.copy( pointOfImpact ).sub( subObject.position ).applyAxisAngle( normal, angle ).add( subObject.position );
+					scope.tempVector3_3.copy( normal ).add( subObject.position );
+					tempPlane2.setFromCoplanarPoints( subObject.position, scope.tempVector3_3, scope.tempVector3_2 );
+
+				}
+
+			}
+
+			// Perform the cut
+			scope.cutByPlane( subObject, tempPlane2, scope.tempResultObjects );
+
+			var obj1 = scope.tempResultObjects.object1;
+			var obj2 = scope.tempResultObjects.object2;
+
+			if ( obj1 ) {
+
+				subdivideRadial( obj1, startAngle, angle, numIterations + 1 );
+
+			}
+
+			if ( obj2 ) {
+
+				subdivideRadial( obj2, angle, endAngle, numIterations + 1 );
+
+			}
+
+		}
+
+		subdivideRadial( object, 0, 2 * Math.PI, 0 );
+
+		return debris;
+
+	},
+
+	cutByPlane: function( object, plane, output ) {
+
+		// Returns breakable objects in output.object1 and output.object2 members, the resulting 2 pieces of the cut.
+		// object2 can be null if the plane doesn't cut the object.
+		// object1 can be null only in case of internal error
+		// Returned value is number of pieces, 0 for error.
+
+		var geometry = object.geometry;
+		var points = geometry.vertices;
+		var faces = geometry.faces;
+
+		var numPoints = points.length;
+
+		var points1 = [];
+		var points2 = [];
+
+		var delta = this.smallDelta;
+
+		// Reset vertices mark
+		for ( var i = 0; i < numPoints; i++ ) {
+			points[ i ].mark = 0;
+		}
+
+		// Reset segments mark
+		var numPointPairs = numPoints * numPoints;
+		for ( var i = 0; i < numPointPairs; i++ ) {
+			this.segments[ i ] = false;
+		}
+
+		// Iterate through the faces to mark edges shared by coplanar faces
+		for ( var i = 0, il = faces.length - 1; i < il; i++ ) {
+
+			var face1 = faces[ i ];
+
+			for ( var j = i + 1, jl = faces.length; j < jl; j++ ) {
+
+				var face2 = faces[ j ];
+
+				var coplanar = 1 - face1.normal.dot( face2.normal ) < delta;
+
+				if ( coplanar ) {
+
+					var a1 = face1.a;
+					var b1 = face1.b;
+					var c1 = face1.c;
+					var a2 = face2.a;
+					var b2 = face2.b;
+					var c2 = face2.c;
+
+
+					if ( a1 === a2 || a1 === b2 || a1 === c2 ) {
+						if ( b1 === a2 || b1 === b2 || b1 === c2 ) {
+							this.segments[ a1 * numPoints + b1 ] = true;
+							this.segments[ b1 * numPoints + a1 ] = true;
+						}
+						else {
+							this.segments[ c1 * numPoints + a1 ] = true;
+							this.segments[ a1 * numPoints + c1 ] = true;
+						}
+					}
+					else if ( b1 === a2 || b1 === b2 || b1 === c2 ) {
+						this.segments[ c1 * numPoints + b1 ] = true;
+						this.segments[ b1 * numPoints + c1 ] = true;
+					}
+
+				}
+
+			}
+
+		}
+
+		// Transform the plane to object local space
+		var localPlane = this.tempPlane1;
+		object.updateMatrix();
+		THREE.ConvexObjectBreaker.transformPlaneToLocalSpace( plane, object.matrix, localPlane );
+
+		// Iterate through the faces adding points to both pieces
+		for ( var i = 0, il = faces.length; i < il; i ++ ) {
+
+			var face = faces[ i ];
+
+			for ( var segment = 0; segment < 3; segment++ ) {
+
+				var i0 = segment === 0 ? face.a : ( segment === 1 ? face.b : face.c );
+				var i1 = segment === 0 ? face.b : ( segment === 1 ? face.c : face.a );
+
+				var segmentState = this.segments[ i0 * numPoints + i1 ];
+
+				if ( segmentState ) {
+					// The segment already has been processed in another face
+					continue;
+				}
+
+				// Mark segment as processed (also inverted segment)
+				this.segments[ i0 * numPoints + i1 ] = true;
+				this.segments[ i1 * numPoints + i0 ] = true;
+
+				var p0 = points[ i0 ];
+				var p1 = points[ i1 ];
+
+				if ( p0.mark === 0 ) {
+
+					var d = localPlane.distanceToPoint( p0 );
+
+					// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
+					if ( d > delta ) {
+						p0.mark = 2;
+						points2.push( p0 );
+					}
+					else if ( d < - delta ) {
+						p0.mark = 1;
+						points1.push( p0 );
+					}
+					else {
+						p0.mark = 3;
+						points1.push( p0 );
+						var p0_2 = p0.clone();
+						p0_2.mark = 3;
+						points2.push( p0_2 );
+					}
+
+				}
+
+				if ( p1.mark === 0 ) {
+
+					var d = localPlane.distanceToPoint( p1 );
+
+					// mark: 1 for negative side, 2 for positive side, 3 for coplanar point
+					if ( d > delta ) {
+						p1.mark = 2;
+						points2.push( p1 );
+					}
+					else if ( d < - delta ) {
+						p1.mark = 1;
+						points1.push( p1 );
+					}
+					else {
+						p1.mark = 3;
+						points1.push( p1 );
+						var p1_2 = p1.clone();
+						p1_2.mark = 3;
+						points2.push( p1_2 );
+					}
+
+				}
+
+				var mark0 = p0.mark;
+				var mark1 = p1.mark;
+
+				if ( ( mark0 === 1 && mark1 === 2 ) || ( mark0 === 2 && mark1 === 1 ) ) {
+
+					// Intersection of segment with the plane
+
+					this.tempLine1.start.copy( p0 );
+					this.tempLine1.end.copy( p1 );
+					var intersection = localPlane.intersectLine( this.tempLine1 );
+					if ( intersection === undefined ) {
+						// Shouldn't happen
+						console.error( "Internal error: segment does not intersect plane." );
+						output.segmentedObject1 = null;
+						output.segmentedObject2 = null;
+						return 0;
+					}
+
+					intersection.mark = 1;
+					points1.push( intersection );
+					var intersection_2 = intersection.clone();
+					intersection_2.mark = 2;
+					points2.push( intersection_2 );
+
+				}
+
+			}
+
+		}
+
+		// Calculate debris mass (very fast and imprecise):
+		var newMass = object.userData.mass * 0.5;
+
+		// Calculate debris Center of Mass (again fast and imprecise)
+		this.tempCM1.set( 0, 0, 0 );
+		var radius1 = 0;
+		var numPoints1 = points1.length;
+		if ( numPoints1 > 0 ) {
+			for ( var i = 0; i < numPoints1; i++ ) {
+				this.tempCM1.add( points1[ i ] );
+			}
+			this.tempCM1.divideScalar( numPoints1 );
+			for ( var i = 0; i < numPoints1; i++ ) {
+				var p = points1[ i ];
+				p.sub( this.tempCM1 );
+				radius1 = Math.max( radius1, p.x, p.y, p.z );
+			}
+			this.tempCM1.add( object.position );
+		}
+
+		this.tempCM2.set( 0, 0, 0 );
+		var radius2 = 0;
+		var numPoints2 = points2.length;
+		if ( numPoints2 > 0 ) {
+			for ( var i = 0; i < numPoints2; i++ ) {
+				this.tempCM2.add( points2[ i ] );
+			}
+			this.tempCM2.divideScalar( numPoints2 );
+			for ( var i = 0; i < numPoints2; i++ ) {
+				var p = points2[ i ];
+				p.sub( this.tempCM2 );
+				radius2 = Math.max( radius2, p.x, p.y, p.z );
+			}
+			this.tempCM2.add( object.position );
+		}
+
+		var object1 = null;
+		var object2 = null;
+
+		var numObjects = 0;
+
+		if ( numPoints1 > 4 ) {
+
+			object1 = new THREE.Mesh( new THREE.ConvexGeometry( points1 ), object.material );
+			object1.position.copy( this.tempCM1 );
+			object1.quaternion.copy( object.quaternion );
+
+			this.prepareBreakableObject( object1, newMass, object.userData.velocity, object.userData.angularVelocity, 2 * radius1 > this.minSizeForBreak );
+
+			numObjects++;
+
+		}
+
+		if ( numPoints2 > 4 ) {
+
+			object2 = new THREE.Mesh( new THREE.ConvexGeometry( points2 ), object.material );
+			object2.position.copy( this.tempCM2 );
+			object2.quaternion.copy( object.quaternion );
+
+			this.prepareBreakableObject( object2, newMass, object.userData.velocity, object.userData.angularVelocity, 2 * radius2 > this.minSizeForBreak );
+
+			numObjects++;
+
+		}
+
+
+		output.object1 = object1;
+		output.object2 = object2;
+
+		return numObjects;
+
+	}
+
+};
+
+THREE.ConvexObjectBreaker.transformFreeVector = function( v, m ) {
+
+	// input:
+	// vector interpreted as a free vector
+	// THREE.Matrix4 orthogonal matrix (matrix without scale)
+
+	var x = v.x, y = v.y, z = v.z;
+	var e = m.elements;
+
+	v.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ]  * z;
+	v.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ]  * z;
+	v.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;
+
+	return v;
+
+};
+
+THREE.ConvexObjectBreaker.transformFreeVectorInverse = function( v, m ) {
+
+	// input:
+	// vector interpreted as a free vector
+	// THREE.Matrix4 orthogonal matrix (matrix without scale)
+
+	var x = v.x, y = v.y, z = v.z;
+	var e = m.elements;
+
+	v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ]  * z;
+	v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ]  * z;
+	v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z;
+
+	return v;
+
+};
+
+THREE.ConvexObjectBreaker.transformTiedVectorInverse = function( v, m ) {
+
+	// input:
+	// vector interpreted as a tied (ordinary) vector
+	// THREE.Matrix4 orthogonal matrix (matrix without scale)
+
+	var x = v.x, y = v.y, z = v.z;
+	var e = m.elements;
+
+	v.x = e[ 0 ] * x + e[ 1 ] * y + e[ 2 ]  * z - e[ 12 ];
+	v.y = e[ 4 ] * x + e[ 5 ] * y + e[ 6 ]  * z - e[ 13 ];
+	v.z = e[ 8 ] * x + e[ 9 ] * y + e[ 10 ] * z - e[ 14 ];
+
+	return v;
+
+};
+
+THREE.ConvexObjectBreaker.transformPlaneToLocalSpace = function() {
+
+	var v1 = new THREE.Vector3();
+	var m1 = new THREE.Matrix3();
+
+	return function transformPlaneToLocalSpace( plane, m, resultPlane ) {
+
+		resultPlane.normal.copy( plane.normal );
+		resultPlane.constant = plane.constant;
+
+		var referencePoint = THREE.ConvexObjectBreaker.transformTiedVectorInverse( plane.coplanarPoint( v1 ), m );
+
+		THREE.ConvexObjectBreaker.transformFreeVectorInverse( resultPlane.normal, m );
+
+		// recalculate constant (like in setFromNormalAndCoplanarPoint)
+		resultPlane.constant = - referencePoint.dot( resultPlane.normal );
+
+
+	};
+
+}();

+ 331 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/CurveExtras.js

@@ -0,0 +1,331 @@
+/*
+ * A bunch of parametric curves
+ * @author zz85
+ *
+ * Formulas collected from various sources
+ *	http://mathworld.wolfram.com/HeartCurve.html
+ *	http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page6.html
+ *	http://en.wikipedia.org/wiki/Viviani%27s_curve
+ *	http://mathdl.maa.org/images/upload_library/23/stemkoski/knots/page4.html
+ *	http://www.mi.sanu.ac.rs/vismath/taylorapril2011/Taylor.pdf
+ *	http://prideout.net/blog/?p=44
+ */
+
+// Lets define some curves
+THREE.Curves = {};
+
+
+ THREE.Curves.GrannyKnot = THREE.Curve.create( function() {},
+
+	 function( t ) {
+
+		t = 2 * Math.PI * t;
+
+		var x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t );
+		var y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t );
+		var z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t );
+		return new THREE.Vector3( x, y, z ).multiplyScalar( 20 );
+
+	}
+);
+
+THREE.Curves.HeartCurve = THREE.Curve.create(
+
+function( s ) {
+
+	this.scale = ( s === undefined ) ? 5 : s;
+
+},
+
+function( t ) {
+
+	t *= 2 * Math.PI;
+
+	var tx = 16 * Math.pow( Math.sin( t ), 3 );
+	var ty = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t ), tz = 0;
+
+	return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+}
+
+);
+
+
+
+// Viviani's Curve
+THREE.Curves.VivianiCurve = THREE.Curve.create(
+
+	function( radius ) {
+
+		this.radius = radius;
+
+	},
+
+	function( t ) {
+
+		t = t * 4 * Math.PI; // Normalized to 0..1
+		var a = this.radius / 2;
+		var tx = a * ( 1 + Math.cos( t ) ),
+			ty = a * Math.sin( t ),
+			tz = 2 * a * Math.sin( t / 2 );
+
+		return new THREE.Vector3( tx, ty, tz );
+
+	}
+
+);
+
+
+THREE.Curves.KnotCurve = THREE.Curve.create(
+
+	function() {
+
+	},
+
+	function( t ) {
+
+		t *= 2 * Math.PI;
+
+		var R = 10;
+		var s = 50;
+		var tx = s * Math.sin( t ),
+			ty = Math.cos( t ) * ( R + s * Math.cos( t ) ),
+			tz = Math.sin( t ) * ( R + s * Math.cos( t ) );
+
+		return new THREE.Vector3( tx, ty, tz );
+
+	}
+
+);
+
+THREE.Curves.HelixCurve = THREE.Curve.create(
+
+	function() {
+
+	},
+
+	function( t ) {
+
+		var a = 30; // radius
+		var b = 150; //height
+		var t2 = 2 * Math.PI * t * b / 30;
+		var tx = Math.cos( t2 ) * a,
+			ty = Math.sin( t2 ) * a,
+			tz = b * t;
+
+		return new THREE.Vector3( tx, ty, tz );
+
+	}
+
+);
+
+THREE.Curves.TrefoilKnot = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 10 : s;
+
+	},
+
+	function( t ) {
+
+		t *= Math.PI * 2;
+		var tx = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t ),
+			ty = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t ),
+			tz = Math.sin( 3 * t );
+
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+THREE.Curves.TorusKnot = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 10 : s;
+
+	},
+
+	function( t ) {
+
+		var p = 3,
+			q = 4;
+		t *= Math.PI * 2;
+		var tx = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ),
+			ty = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ),
+			tz = Math.sin( q * t );
+
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+
+THREE.Curves.CinquefoilKnot = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 10 : s;
+
+	},
+
+	function( t ) {
+
+		var p = 2,
+			q = 5;
+		t *= Math.PI * 2;
+		var tx = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ),
+			ty = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ),
+			tz = Math.sin( q * t );
+
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+
+THREE.Curves.TrefoilPolynomialKnot = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 10 : s;
+
+	},
+
+	function( t ) {
+
+		t = t * 4 - 2;
+		var tx = Math.pow( t, 3 ) - 3 * t,
+			ty = Math.pow( t, 4 ) - 4 * t * t,
+			tz = 1 / 5 * Math.pow( t, 5 ) - 2 * t;
+
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+// var scaleTo = function(x, y) {
+//   var r = y - x;
+//   return function(t) {
+//     t * r + x;
+//   };
+// }
+var scaleTo = function( x, y, t ) {
+
+	var r = y - x;
+	return t * r + x;
+
+};
+
+THREE.Curves.FigureEightPolynomialKnot = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 1 : s;
+
+	},
+
+	function( t ) {
+
+		t = scaleTo( - 4, 4, t );
+		var tx = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 ),
+			ty = Math.pow( t, 4 ) - 13 * t * t,
+			tz = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 );
+
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+THREE.Curves.DecoratedTorusKnot4a = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 40 : s;
+
+	},
+
+	function( t ) {
+
+		t *= Math.PI * 2;
+		var
+		x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ),
+			y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ),
+			z = 0.35 * Math.sin( 5 * t );
+
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+
+THREE.Curves.DecoratedTorusKnot4b = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 40 : s;
+
+	},
+
+	function( t ) {
+
+		var fi = t * Math.PI * 2;
+		var x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ),
+			y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ),
+			z = 0.2 * Math.sin( 9 * fi );
+
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+
+THREE.Curves.DecoratedTorusKnot5a = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 40 : s;
+
+	},
+
+	function( t ) {
+
+		var fi = t * Math.PI * 2;
+		var x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ),
+			y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ),
+			z = 0.2 * Math.sin( 20 * fi );
+
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
+
+	}
+
+);
+
+THREE.Curves.DecoratedTorusKnot5c = THREE.Curve.create(
+
+	function( s ) {
+
+		this.scale = ( s === undefined ) ? 40 : s;
+
+	},
+
+	function( t ) {
+
+		var fi = t * Math.PI * 2;
+		var x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ),
+			y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ),
+			z = 0.35 * Math.sin( 15 * fi );
+
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
+
+	}
+
+);

+ 78 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Detector.js

@@ -0,0 +1,78 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+var Detector = {
+
+	canvas: !! window.CanvasRenderingContext2D,
+	webgl: ( function () {
+
+		try {
+
+			var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) );
+
+		} catch ( e ) {
+
+			return false;
+
+		}
+
+	} )(),
+	workers: !! window.Worker,
+	fileapi: window.File && window.FileReader && window.FileList && window.Blob,
+
+	getWebGLErrorMessage: function () {
+
+		var element = document.createElement( 'div' );
+		element.id = 'webgl-error-message';
+		element.style.fontFamily = 'monospace';
+		element.style.fontSize = '13px';
+		element.style.fontWeight = 'normal';
+		element.style.textAlign = 'center';
+		element.style.background = '#fff';
+		element.style.color = '#000';
+		element.style.padding = '1.5em';
+		element.style.width = '400px';
+		element.style.margin = '5em auto 0';
+
+		if ( ! this.webgl ) {
+
+			element.innerHTML = window.WebGLRenderingContext ? [
+				'Your graphics card does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br />',
+				'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
+			].join( '\n' ) : [
+				'Your browser does not seem to support <a href="http://khronos.org/webgl/wiki/Getting_a_WebGL_Implementation" style="color:#000">WebGL</a>.<br/>',
+				'Find out how to get it <a href="http://get.webgl.org/" style="color:#000">here</a>.'
+			].join( '\n' );
+
+		}
+
+		return element;
+
+	},
+
+	addGetWebGLMessage: function ( parameters ) {
+
+		var parent, id, element;
+
+		parameters = parameters || {};
+
+		parent = parameters.parent !== undefined ? parameters.parent : document.body;
+		id = parameters.id !== undefined ? parameters.id : 'oldie';
+
+		element = Detector.getWebGLErrorMessage();
+		element.id = id;
+
+		parent.appendChild( element );
+
+	}
+
+};
+
+// browserify support
+if ( typeof module === 'object' ) {
+
+	module.exports = Detector;
+
+}

+ 370 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/GPUComputationRenderer.js

@@ -0,0 +1,370 @@
+/**
+ * @author yomboprime https://github.com/yomboprime
+ *
+ * GPUComputationRenderer, based on SimulationRenderer by zz85
+ *
+ * The GPUComputationRenderer uses the concept of variables. These variables are RGBA float textures that hold 4 floats
+ * for each compute element (texel)
+ *
+ * Each variable has a fragment shader that defines the computation made to obtain the variable in question.
+ * You can use as many variables you need, and make dependencies so you can use textures of other variables in the shader
+ * (the sampler uniforms are added automatically) Most of the variables will need themselves as dependency.
+ *
+ * The renderer has actually two render targets per variable, to make ping-pong. Textures from the current frame are used
+ * as inputs to render the textures of the next frame.
+ *
+ * The render targets of the variables can be used as input textures for your visualization shaders.
+ *
+ * Variable names should be valid identifiers and should not collide with THREE GLSL used identifiers.
+ * a common approach could be to use 'texture' prefixing the variable name; i.e texturePosition, textureVelocity...
+ *
+ * The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:
+ * #DEFINE resolution vec2( 1024.0, 1024.0 )
+ *
+ * -------------
+ *
+ * Basic use:
+ *
+ * // Initialization...
+ *
+ * // Create computation renderer
+ * var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
+ *
+ * // Create initial state float textures
+ * var pos0 = gpuCompute.createTexture();
+ * var vel0 = gpuCompute.createTexture();
+ * // and fill in here the texture data...
+ *
+ * // Add texture variables
+ * var velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
+ * var posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
+ *
+ * // Add variable dependencies
+ * gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );
+ * gpuCompute.setVariableDependencies( posVar, [ velVar, posVar ] );
+ *
+ * // Add custom uniforms
+ * velVar.material.uniforms.time = { value: 0.0 };
+ *
+ * // Check for completeness
+ * var error = gpuCompute.init();
+ * if ( error !== null ) {
+ *		console.error( error );
+  * }
+ *
+ *
+ * // In each frame...
+ *
+ * // Compute!
+ * gpuCompute.compute();
+ *
+ * // Update texture uniforms in your visualization materials with the gpu renderer output
+ * myMaterial.uniforms.myTexture.value = gpuCompute.getCurrentRenderTarget( posVar ).texture;
+ *
+ * // Do your rendering
+ * renderer.render( myScene, myCamera );
+ *
+ * -------------
+ *
+ * Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures)
+ * Note that the shaders can have multiple input textures.
+ *
+ * var myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
+ * var myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
+ *
+ * var inputTexture = gpuCompute.createTexture();
+ *
+ * // Fill in here inputTexture...
+ *
+ * myFilter1.uniforms.theTexture.value = inputTexture;
+ *
+ * var myRenderTarget = gpuCompute.createRenderTarget();
+ * myFilter2.uniforms.theTexture.value = myRenderTarget.texture;
+ *
+ * var outputRenderTarget = gpuCompute.createRenderTarget();
+ *
+ * // Now use the output texture where you want:
+ * myMaterial.uniforms.map.value = outputRenderTarget.texture;
+ *
+ * // And compute each frame, before rendering to screen:
+ * gpuCompute.doRenderTarget( myFilter1, myRenderTarget );
+ * gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
+ * 
+ *
+ *
+ * @param {int} sizeX Computation problem size is always 2d: sizeX * sizeY elements.
+ * @param {int} sizeY Computation problem size is always 2d: sizeX * sizeY elements.
+ * @param {WebGLRenderer} renderer The renderer
+  */
+
+function GPUComputationRenderer( sizeX, sizeY, renderer ) {
+
+	this.variables = [];
+
+	this.currentTextureIndex = 0;
+
+	var scene = new THREE.Scene();
+
+	var camera = new THREE.Camera();
+	camera.position.z = 1;
+
+	var passThruUniforms = {
+		texture: { value: null }
+	};
+
+	var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
+
+	var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), passThruShader );
+	scene.add( mesh );
+
+
+	this.addVariable = function( variableName, computeFragmentShader, initialValueTexture ) {
+
+		var material = this.createShaderMaterial( computeFragmentShader );
+
+		var variable = {
+			name: variableName,
+			initialValueTexture: initialValueTexture,
+			material: material,
+			dependencies: null,
+			renderTargets: [],
+			wrapS: null,
+			wrapT: null,
+			minFilter: THREE.NearestFilter,
+			magFilter: THREE.NearestFilter
+		};
+
+		this.variables.push( variable );
+
+		return variable;
+		
+	};
+
+	this.setVariableDependencies = function( variable, dependencies ) {
+
+		variable.dependencies = dependencies;
+
+	};
+
+	this.init = function() {
+
+		if ( ! renderer.extensions.get( "OES_texture_float" ) ) {
+
+			return "No OES_texture_float support for float textures.";
+
+		}
+
+		if ( renderer.capabilities.maxVertexTextures === 0 ) {
+
+			return "No support for vertex shader textures.";
+
+		}
+
+		for ( var i = 0; i < this.variables.length; i++ ) {
+
+			var variable = this.variables[ i ];
+
+			// Creates rendertargets and initialize them with input texture
+			variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
+			variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
+			this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
+			this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] );
+
+			// Adds dependencies uniforms to the ShaderMaterial
+			var material = variable.material;
+			var uniforms = material.uniforms;
+			if ( variable.dependencies !== null ) {
+
+				for ( var d = 0; d < variable.dependencies.length; d++ ) {
+
+					var depVar = variable.dependencies[ d ];
+
+					if ( depVar.name !== variable.name ) {
+
+						// Checks if variable exists
+						var found = false;
+						for ( var j = 0; j < this.variables.length; j++ ) {
+
+							if ( depVar.name === this.variables[ j ].name ) {
+								found = true;
+								break;
+							}
+
+						}
+						if ( ! found ) {
+							return "Variable dependency not found. Variable=" + variable.name + ", dependency=" + depVar.name;
+						}
+
+					}
+
+					uniforms[ depVar.name ] = { value: null };
+
+					material.fragmentShader = "\nuniform sampler2D " + depVar.name + ";\n" + material.fragmentShader;
+
+				}
+			}
+		}
+
+		this.currentTextureIndex = 0;
+
+		return null;
+
+	};
+
+	this.compute = function() {
+
+		var currentTextureIndex = this.currentTextureIndex;
+		var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
+
+		for ( var i = 0, il = this.variables.length; i < il; i++ ) {
+
+			var variable = this.variables[ i ];
+
+			// Sets texture dependencies uniforms
+			if ( variable.dependencies !== null ) {
+
+				var uniforms = variable.material.uniforms;
+				for ( var d = 0, dl = variable.dependencies.length; d < dl; d++ ) {
+
+					var depVar = variable.dependencies[ d ];
+
+					uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
+
+				}
+
+			}
+
+			// Performs the computation for this variable
+			this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
+
+		}
+
+		this.currentTextureIndex = nextTextureIndex;
+	};
+
+	this.getCurrentRenderTarget = function( variable ) {
+
+		return variable.renderTargets[ this.currentTextureIndex ];
+
+	};
+
+	this.getAlternateRenderTarget = function( variable ) {
+
+		return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
+
+	};
+
+	function addResolutionDefine( materialShader ) {
+
+		materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + " )";
+
+	}
+	this.addResolutionDefine = addResolutionDefine;
+
+
+	// The following functions can be used to compute things manually
+
+	function createShaderMaterial( computeFragmentShader, uniforms ) {
+
+		uniforms = uniforms || {};
+
+		var material = new THREE.ShaderMaterial( {
+			uniforms: uniforms,
+			vertexShader: getPassThroughVertexShader(),
+			fragmentShader: computeFragmentShader
+		} );
+
+		addResolutionDefine( material );
+
+		return material;
+	}
+	this.createShaderMaterial = createShaderMaterial;
+
+	this.createRenderTarget = function( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
+
+		sizeXTexture = sizeXTexture || sizeX;
+		sizeYTexture = sizeYTexture || sizeY;
+
+		wrapS = wrapS || THREE.ClampToEdgeWrapping;
+		wrapT = wrapT || THREE.ClampToEdgeWrapping;
+
+		minFilter = minFilter || THREE.NearestFilter;
+		magFilter = magFilter || THREE.NearestFilter;
+
+		var renderTarget = new THREE.WebGLRenderTarget( sizeXTexture, sizeYTexture, {
+			wrapS: wrapS,
+			wrapT: wrapT,
+			minFilter: minFilter,
+			magFilter: magFilter,
+			format: THREE.RGBAFormat,
+			type: ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) ? THREE.HalfFloatType : THREE.FloatType,
+			stencilBuffer: false
+		} );
+
+		return renderTarget;
+
+	};
+
+    this.createTexture = function( sizeXTexture, sizeYTexture ) {
+
+		sizeXTexture = sizeXTexture || sizeX;
+		sizeYTexture = sizeYTexture || sizeY;
+
+		var a = new Float32Array( sizeXTexture * sizeYTexture * 4 );
+		var texture = new THREE.DataTexture( a, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
+		texture.needsUpdate = true;
+
+		return texture;
+
+	};
+
+
+	this.renderTexture = function( input, output ) {
+
+		// Takes a texture, and render out in rendertarget
+		// input = Texture
+		// output = RenderTarget
+
+		passThruUniforms.texture.value = input;
+
+		this.doRenderTarget( passThruShader, output);
+
+		passThruUniforms.texture.value = null;
+
+	};
+
+	this.doRenderTarget = function( material, output ) {
+
+		mesh.material = material;
+		renderer.render( scene, camera, output );
+		mesh.material = passThruShader;
+
+	};
+
+	// Shaders
+
+	function getPassThroughVertexShader() {
+
+		return	"void main()	{\n" +
+				"\n" +
+				"	gl_Position = vec4( position, 1.0 );\n" +
+				"\n" +
+				"}\n";
+
+	}
+
+	function getPassThroughFragmentShader() {
+
+		return	"uniform sampler2D texture;\n" +
+				"\n" +
+				"void main() {\n" +
+				"\n" +
+				"	vec2 uv = gl_FragCoord.xy / resolution.xy;\n" +
+				"\n" +
+				"	gl_FragColor = texture2D( texture, uv );\n" +
+				"\n" +
+				"}\n";
+
+	}
+
+}

+ 508 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/GPUParticleSystem.js

@@ -0,0 +1,508 @@
+/*
+ * GPU Particle System
+ * @author flimshaw - Charlie Hoey - http://charliehoey.com
+ *
+ * A simple to use, general purpose GPU system. Particles are spawn-and-forget with
+ * several options available, and do not require monitoring or cleanup after spawning.
+ * Because the paths of all particles are completely deterministic once spawned, the scale
+ * and direction of time is also variable.
+ *
+ * Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for
+ * particles, but adding support for a particle texture atlas or changing to a different type of turbulence
+ * would be a fairly light day's work.
+ *
+ * Shader and javascript packing code derrived from several Stack Overflow examples.
+ *
+ */
+
+THREE.GPUParticleSystem = function(options) {
+
+	var self = this;
+	var options = options || {};
+
+	// parse options and use defaults
+	self.PARTICLE_COUNT = options.maxParticles || 1000000;
+	self.PARTICLE_CONTAINERS = options.containerCount || 1;
+	
+	self.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null;
+	self.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null;
+	
+	self.PARTICLES_PER_CONTAINER = Math.ceil(self.PARTICLE_COUNT / self.PARTICLE_CONTAINERS);
+	self.PARTICLE_CURSOR = 0;
+	self.time = 0;
+
+
+	// Custom vertex and fragement shader
+	var GPUParticleShader = {
+
+		vertexShader: [
+
+			'precision highp float;',
+			'const vec4 bitSh = vec4(256. * 256. * 256., 256. * 256., 256., 1.);',
+			'const vec4 bitMsk = vec4(0.,vec3(1./256.0));',
+			'const vec4 bitShifts = vec4(1.) / bitSh;',
+
+			'#define FLOAT_MAX	1.70141184e38',
+			'#define FLOAT_MIN	1.17549435e-38',
+
+			'lowp vec4 encode_float(highp float v) {',
+			'highp float av = abs(v);',
+
+			'//Handle special cases',
+			'if(av < FLOAT_MIN) {',
+			'return vec4(0.0, 0.0, 0.0, 0.0);',
+			'} else if(v > FLOAT_MAX) {',
+			'return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;',
+			'} else if(v < -FLOAT_MAX) {',
+			'return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;',
+			'}',
+
+			'highp vec4 c = vec4(0,0,0,0);',
+
+			'//Compute exponent and mantissa',
+			'highp float e = floor(log2(av));',
+			'highp float m = av * pow(2.0, -e) - 1.0;',
+
+			//Unpack mantissa
+			'c[1] = floor(128.0 * m);',
+			'm -= c[1] / 128.0;',
+			'c[2] = floor(32768.0 * m);',
+			'm -= c[2] / 32768.0;',
+			'c[3] = floor(8388608.0 * m);',
+
+			'//Unpack exponent',
+			'highp float ebias = e + 127.0;',
+			'c[0] = floor(ebias / 2.0);',
+			'ebias -= c[0] * 2.0;',
+			'c[1] += floor(ebias) * 128.0;',
+
+			'//Unpack sign bit',
+			'c[0] += 128.0 * step(0.0, -v);',
+
+			'//Scale back to range',
+			'return c / 255.0;',
+			'}',
+
+			'vec4 pack(const in float depth)',
+			'{',
+			'const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);',
+			'const vec4 bit_mask	= vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);',
+			'vec4 res = mod(depth*bit_shift*vec4(255), vec4(256))/vec4(255);',
+			'res -= res.xxyz * bit_mask;',
+			'return res;',
+			'}',
+
+			'float unpack(const in vec4 rgba_depth)',
+			'{',
+			'const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);',
+			'float depth = dot(rgba_depth, bit_shift);',
+			'return depth;',
+			'}',
+
+			'uniform float uTime;',
+			'uniform float uScale;',
+			'uniform sampler2D tNoise;',
+
+			'attribute vec4 particlePositionsStartTime;',
+			'attribute vec4 particleVelColSizeLife;',
+
+			'varying vec4 vColor;',
+			'varying float lifeLeft;',
+
+			'void main() {',
+
+			'// unpack things from our attributes',
+			'vColor = encode_float( particleVelColSizeLife.y );',
+
+			'// convert our velocity back into a value we can use',
+			'vec4 velTurb = encode_float( particleVelColSizeLife.x );',
+			'vec3 velocity = vec3( velTurb.xyz );',
+			'float turbulence = velTurb.w;',
+
+			'vec3 newPosition;',
+
+			'float timeElapsed = uTime - particlePositionsStartTime.a;',
+
+			'lifeLeft = 1. - (timeElapsed / particleVelColSizeLife.w);',
+
+			'gl_PointSize = ( uScale * particleVelColSizeLife.z ) * lifeLeft;',
+
+			'velocity.x = ( velocity.x - .5 ) * 3.;',
+			'velocity.y = ( velocity.y - .5 ) * 3.;',
+			'velocity.z = ( velocity.z - .5 ) * 3.;',
+
+			'newPosition = particlePositionsStartTime.xyz + ( velocity * 10. ) * ( uTime - particlePositionsStartTime.a );',
+
+			'vec3 noise = texture2D( tNoise, vec2( newPosition.x * .015 + (uTime * .05), newPosition.y * .02 + (uTime * .015) )).rgb;',
+			'vec3 noiseVel = ( noise.rgb - .5 ) * 30.;',
+
+			'newPosition = mix(newPosition, newPosition + vec3(noiseVel * ( turbulence * 5. ) ), (timeElapsed / particleVelColSizeLife.a) );',
+
+			'if( velocity.y > 0. && velocity.y < .05 ) {',
+			'lifeLeft = 0.;',
+			'}',
+
+			'if( velocity.x < -1.45 ) {',
+			'lifeLeft = 0.;',
+			'}',
+
+			'if( timeElapsed > 0. ) {',
+			'gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
+			'} else {',
+			'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+			'lifeLeft = 0.;',
+			'gl_PointSize = 0.;',
+			'}',
+			'}'
+
+		].join("\n"),
+
+		fragmentShader: [
+
+			'float scaleLinear(float value, vec2 valueDomain) {',
+			'return (value - valueDomain.x) / (valueDomain.y - valueDomain.x);',
+			'}',
+
+			'float scaleLinear(float value, vec2 valueDomain, vec2 valueRange) {',
+			'return mix(valueRange.x, valueRange.y, scaleLinear(value, valueDomain));',
+			'}',
+
+			'varying vec4 vColor;',
+			'varying float lifeLeft;',
+
+			'uniform sampler2D tSprite;',
+
+			'void main() {',
+
+			'float alpha = 0.;',
+
+			'if( lifeLeft > .995 ) {',
+			'alpha = scaleLinear( lifeLeft, vec2(1., .995), vec2(0., 1.));//mix( 0., 1., ( lifeLeft - .95 ) * 100. ) * .75;',
+			'} else {',
+			'alpha = lifeLeft * .75;',
+			'}',
+
+			'vec4 tex = texture2D( tSprite, gl_PointCoord );',
+
+			'gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
+			'}'
+
+		].join("\n")
+
+	};
+
+	// preload a million random numbers
+	self.rand = [];
+
+	for (var i = 1e5; i > 0; i--) {
+		self.rand.push(Math.random() - .5);
+	}
+
+	self.random = function() {
+		return ++i >= self.rand.length ? self.rand[i = 1] : self.rand[i];
+	};
+
+	var textureLoader = new THREE.TextureLoader();
+
+	self.particleNoiseTex = self.PARTICLE_NOISE_TEXTURE || textureLoader.load("textures/perlin-512.png");
+	self.particleNoiseTex.wrapS = self.particleNoiseTex.wrapT = THREE.RepeatWrapping;
+
+	self.particleSpriteTex = self.PARTICLE_SPRITE_TEXTURE || textureLoader.load("textures/particle2.png");
+	self.particleSpriteTex.wrapS = self.particleSpriteTex.wrapT = THREE.RepeatWrapping;
+
+	self.particleShaderMat = new THREE.ShaderMaterial({
+		transparent: true,
+		depthWrite: false,
+		uniforms: {
+			"uTime": {
+				value: 0.0
+			},
+			"uScale": {
+				value: 1.0
+			},
+			"tNoise": {
+				value: self.particleNoiseTex
+			},
+			"tSprite": {
+				value: self.particleSpriteTex
+			}
+		},
+		blending: THREE.AdditiveBlending,
+		vertexShader: GPUParticleShader.vertexShader,
+		fragmentShader: GPUParticleShader.fragmentShader
+	});
+
+	// define defaults for all values
+	self.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [0, 0, 0, 0];
+	self.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [0, 0, 0, 0];
+
+	self.particleContainers = [];
+
+
+	// extend Object3D
+	THREE.Object3D.apply(this, arguments);
+
+	this.init = function() {
+
+		for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+			var c = new THREE.GPUParticleContainer(self.PARTICLES_PER_CONTAINER, self);
+			self.particleContainers.push(c);
+			self.add(c);
+
+		}
+
+	};
+
+	this.spawnParticle = function(options) {
+
+		self.PARTICLE_CURSOR++;
+		if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+			self.PARTICLE_CURSOR = 1;
+		}
+
+		var currentContainer = self.particleContainers[Math.floor(self.PARTICLE_CURSOR / self.PARTICLES_PER_CONTAINER)];
+
+		currentContainer.spawnParticle(options);
+
+	};
+
+	this.update = function(time) {
+		for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+			self.particleContainers[i].update(time);
+
+		}
+	};
+
+	this.init();
+
+};
+
+THREE.GPUParticleSystem.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem;
+
+
+// Subclass for particle containers, allows for very large arrays to be spread out
+THREE.GPUParticleContainer = function(maxParticles, particleSystem) {
+
+	var self = this;
+	self.PARTICLE_COUNT = maxParticles || 100000;
+	self.PARTICLE_CURSOR = 0;
+	self.time = 0;
+	self.DPR = window.devicePixelRatio;
+	self.GPUParticleSystem = particleSystem;
+
+	var particlesPerArray = Math.floor(self.PARTICLE_COUNT / self.MAX_ATTRIBUTES);
+
+	// extend Object3D
+	THREE.Object3D.apply(this, arguments);
+
+	// construct a couple small arrays used for packing variables into floats etc
+	var UINT8_VIEW = new Uint8Array(4);
+	var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer);
+
+	function decodeFloat(x, y, z, w) {
+		UINT8_VIEW[0] = Math.floor(w);
+		UINT8_VIEW[1] = Math.floor(z);
+		UINT8_VIEW[2] = Math.floor(y);
+		UINT8_VIEW[3] = Math.floor(x);
+		return FLOAT_VIEW[0]
+	}
+
+	function componentToHex(c) {
+		var hex = c.toString(16);
+		return hex.length == 1 ? "0" + hex : hex;
+	}
+
+	function rgbToHex(r, g, b) {
+		return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+	}
+
+	function hexToRgb(hex) {
+		var r = hex >> 16;
+		var g = (hex & 0x00FF00) >> 8;
+		var b = hex & 0x0000FF;
+
+		if (r > 0) r--;
+		if (g > 0) g--;
+		if (b > 0) b--;
+
+		return [r, g, b];
+	}
+
+	self.particles = [];
+	self.deadParticles = [];
+	self.particlesAvailableSlot = [];
+
+	// create a container for particles
+	self.particleUpdate = false;
+
+	// Shader Based Particle System
+	self.particleShaderGeo = new THREE.BufferGeometry();
+
+	// new hyper compressed attributes
+	self.particleVertices = new Float32Array(self.PARTICLE_COUNT * 3); // position
+	self.particlePositionsStartTime = new Float32Array(self.PARTICLE_COUNT * 4); // position
+	self.particleVelColSizeLife = new Float32Array(self.PARTICLE_COUNT * 4);
+
+	for (var i = 0; i < self.PARTICLE_COUNT; i++) {
+		self.particlePositionsStartTime[i * 4 + 0] = 100; //x
+		self.particlePositionsStartTime[i * 4 + 1] = 0; //y
+		self.particlePositionsStartTime[i * 4 + 2] = 0.0; //z
+		self.particlePositionsStartTime[i * 4 + 3] = 0.0; //startTime
+
+		self.particleVertices[i * 3 + 0] = 0; //x
+		self.particleVertices[i * 3 + 1] = 0; //y
+		self.particleVertices[i * 3 + 2] = 0.0; //z
+
+		self.particleVelColSizeLife[i * 4 + 0] = decodeFloat(128, 128, 0, 0); //vel
+		self.particleVelColSizeLife[i * 4 + 1] = decodeFloat(0, 254, 0, 254); //color
+		self.particleVelColSizeLife[i * 4 + 2] = 1.0; //size
+		self.particleVelColSizeLife[i * 4 + 3] = 0.0; //lifespan
+	}
+
+	self.particleShaderGeo.addAttribute('position', new THREE.BufferAttribute(self.particleVertices, 3));
+	self.particleShaderGeo.addAttribute('particlePositionsStartTime', new THREE.BufferAttribute(self.particlePositionsStartTime, 4).setDynamic(true));
+	self.particleShaderGeo.addAttribute('particleVelColSizeLife', new THREE.BufferAttribute(self.particleVelColSizeLife, 4).setDynamic(true));
+
+	self.posStart = self.particleShaderGeo.getAttribute('particlePositionsStartTime');
+	self.velCol = self.particleShaderGeo.getAttribute('particleVelColSizeLife');
+
+	self.particleShaderMat = self.GPUParticleSystem.particleShaderMat;
+
+	this.init = function() {
+		self.particleSystem = new THREE.Points(self.particleShaderGeo, self.particleShaderMat);
+		self.particleSystem.frustumCulled = false;
+		this.add(self.particleSystem);
+	};
+
+	var options = {},
+		position = new THREE.Vector3(),
+		velocity = new THREE.Vector3(),
+		positionRandomness = 0.,
+		velocityRandomness = 0.,
+		color = 0xffffff,
+		colorRandomness = 0.,
+		turbulence = 0.,
+		lifetime = 0.,
+		size = 0.,
+		sizeRandomness = 0.,
+		smoothPosition = false,
+		i;
+
+	var maxVel = 2;
+	var maxSource = 250;
+	this.offset = 0;
+	this.count = 0;
+
+	this.spawnParticle = function(options) {
+
+		options = options || {};
+
+		// setup reasonable default values for all arguments
+		position = options.position !== undefined ? position.copy(options.position) : position.set(0., 0., 0.);
+		velocity = options.velocity !== undefined ? velocity.copy(options.velocity) : velocity.set(0., 0., 0.);
+		positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0.0;
+		velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0.0;
+		color = options.color !== undefined ? options.color : 0xffffff;
+		colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1.0;
+		turbulence = options.turbulence !== undefined ? options.turbulence : 1.0;
+		lifetime = options.lifetime !== undefined ? options.lifetime : 5.0;
+		size = options.size !== undefined ? options.size : 10;
+		sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0.0;
+		smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
+
+		if (self.DPR !== undefined) size *= self.DPR;
+
+		i = self.PARTICLE_CURSOR;
+
+		self.posStart.array[i * 4 + 0] = position.x + ((particleSystem.random()) * positionRandomness); // - ( velocity.x * particleSystem.random() ); //x
+		self.posStart.array[i * 4 + 1] = position.y + ((particleSystem.random()) * positionRandomness); // - ( velocity.y * particleSystem.random() ); //y
+		self.posStart.array[i * 4 + 2] = position.z + ((particleSystem.random()) * positionRandomness); // - ( velocity.z * particleSystem.random() ); //z
+		self.posStart.array[i * 4 + 3] = self.time + (particleSystem.random() * 2e-2); //startTime
+
+		if (smoothPosition === true) {
+			self.posStart.array[i * 4 + 0] += -(velocity.x * particleSystem.random()); //x
+			self.posStart.array[i * 4 + 1] += -(velocity.y * particleSystem.random()); //y
+			self.posStart.array[i * 4 + 2] += -(velocity.z * particleSystem.random()); //z
+		}
+
+		var velX = velocity.x + (particleSystem.random()) * velocityRandomness;
+		var velY = velocity.y + (particleSystem.random()) * velocityRandomness;
+		var velZ = velocity.z + (particleSystem.random()) * velocityRandomness;
+
+		// convert turbulence rating to something we can pack into a vec4
+		var turbulence = Math.floor(turbulence * 254);
+
+		// clamp our value to between 0. and 1.
+		velX = Math.floor(maxSource * ((velX - -maxVel) / (maxVel - -maxVel)));
+		velY = Math.floor(maxSource * ((velY - -maxVel) / (maxVel - -maxVel)));
+		velZ = Math.floor(maxSource * ((velZ - -maxVel) / (maxVel - -maxVel)));
+
+		self.velCol.array[i * 4 + 0] = decodeFloat(velX, velY, velZ, turbulence); //vel
+
+		var rgb = hexToRgb(color);
+
+		for (var c = 0; c < rgb.length; c++) {
+			rgb[c] = Math.floor(rgb[c] + ((particleSystem.random()) * colorRandomness) * 254);
+			if (rgb[c] > 254) rgb[c] = 254;
+			if (rgb[c] < 0) rgb[c] = 0;
+		}
+
+		self.velCol.array[i * 4 + 1] = decodeFloat(rgb[0], rgb[1], rgb[2], 254); //color
+		self.velCol.array[i * 4 + 2] = size + (particleSystem.random()) * sizeRandomness; //size
+		self.velCol.array[i * 4 + 3] = lifetime; //lifespan
+
+		if (this.offset == 0) {
+			this.offset = self.PARTICLE_CURSOR;
+		}
+
+		self.count++;
+
+		self.PARTICLE_CURSOR++;
+
+		if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+			self.PARTICLE_CURSOR = 0;
+		}
+
+		self.particleUpdate = true;
+
+	};
+
+	this.update = function(time) {
+
+		self.time = time;
+		self.particleShaderMat.uniforms['uTime'].value = time;
+
+		this.geometryUpdate();
+
+	};
+
+	this.geometryUpdate = function() {
+		if (self.particleUpdate == true) {
+			self.particleUpdate = false;
+
+			// if we can get away with a partial buffer update, do so
+			if (self.offset + self.count < self.PARTICLE_COUNT) {
+				self.posStart.updateRange.offset = self.velCol.updateRange.offset = self.offset * 4;
+				self.posStart.updateRange.count = self.velCol.updateRange.count = self.count * 4;
+			} else {
+				self.posStart.updateRange.offset = 0;
+				self.posStart.updateRange.count = self.velCol.updateRange.count = (self.PARTICLE_COUNT * 4);
+			}
+
+			self.posStart.needsUpdate = true;
+			self.velCol.needsUpdate = true;
+
+			self.offset = 0;
+			self.count = 0;
+		}
+	};
+
+	this.init();
+
+};
+
+THREE.GPUParticleContainer.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer;

+ 65 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Gyroscope.js

@@ -0,0 +1,65 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Gyroscope = function () {
+
+	THREE.Object3D.call( this );
+
+};
+
+THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
+THREE.Gyroscope.prototype.constructor = THREE.Gyroscope;
+
+THREE.Gyroscope.prototype.updateMatrixWorld = ( function () {
+
+	var translationObject = new THREE.Vector3();
+	var quaternionObject = new THREE.Quaternion();
+	var scaleObject = new THREE.Vector3();
+
+	var translationWorld = new THREE.Vector3();
+	var quaternionWorld = new THREE.Quaternion();
+	var scaleWorld = new THREE.Vector3();
+
+	return function updateMatrixWorld( force ) {
+
+		this.matrixAutoUpdate && this.updateMatrix();
+
+		// update matrixWorld
+
+		if ( this.matrixWorldNeedsUpdate || force ) {
+
+			if ( this.parent !== null ) {
+
+				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
+
+				this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld );
+				this.matrix.decompose( translationObject, quaternionObject, scaleObject );
+
+				this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld );
+
+
+			} else {
+
+				this.matrixWorld.copy( this.matrix );
+
+			}
+
+
+			this.matrixWorldNeedsUpdate = false;
+
+			force = true;
+
+		}
+
+		// update children
+
+		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+
+			this.children[ i ].updateMatrixWorld( force );
+
+		}
+
+	};
+
+}() );

+ 71 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ImprovedNoise.js

@@ -0,0 +1,71 @@
+// http://mrl.nyu.edu/~perlin/noise/
+
+var ImprovedNoise = function () {
+
+	var p = [ 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,
+		 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,
+		 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,
+		 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,
+		 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,
+		 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,
+		 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
+		 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,
+		 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,
+		 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ];
+
+	for (var i = 0; i < 256 ; i ++) {
+
+		p[256 + i] = p[i];
+
+	}
+
+	function fade(t) {
+
+		return t * t * t * (t * (t * 6 - 15) + 10);
+
+	}
+
+	function lerp(t, a, b) {
+
+		return a + t * (b - a);
+
+	}
+
+	function grad(hash, x, y, z) {
+
+		var h = hash & 15;
+		var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+		return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
+
+	}
+
+	return {
+
+		noise: function (x, y, z) {
+
+			var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
+
+			var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
+
+			x -= floorX;
+			y -= floorY;
+			z -= floorZ;
+
+			var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
+
+			var u = fade(x), v = fade(y), w = fade(z);
+
+			var A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
+
+			return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
+							grad(p[BA], xMinus1, y, z)),
+						lerp(u, grad(p[AB], x, yMinus1, z),
+							grad(p[BB], xMinus1, yMinus1, z))),
+					lerp(v, lerp(u, grad(p[AA + 1], x, y, zMinus1),
+							grad(p[BA + 1], xMinus1, y, z - 1)),
+						lerp(u, grad(p[AB + 1], x, yMinus1, zMinus1),
+							grad(p[BB + 1], xMinus1, yMinus1, zMinus1))));
+
+		}
+	}
+};

+ 254 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MD2Character.js

@@ -0,0 +1,254 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MD2Character = function () {
+
+	var scope = this;
+
+	this.scale = 1;
+	this.animationFPS = 6;
+
+	this.root = new THREE.Object3D();
+
+	this.meshBody = null;
+	this.meshWeapon = null;
+
+	this.skinsBody = [];
+	this.skinsWeapon = [];
+
+	this.weapons = [];
+
+	this.activeAnimation = null;
+
+	this.mixer = null;
+
+	this.onLoadComplete = function () {};
+
+	this.loadCounter = 0;
+
+	this.loadParts = function ( config ) {
+
+		this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
+
+		var weaponsTextures = [];
+		for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
+		// SKINS
+
+		this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
+		this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
+
+		// BODY
+
+		var loader = new THREE.MD2Loader();
+
+		loader.load( config.baseUrl + config.body, function( geo ) {
+
+			geo.computeBoundingBox();
+			scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
+
+			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
+			mesh.scale.set( scope.scale, scope.scale, scope.scale );
+
+			scope.root.add( mesh );
+
+			scope.meshBody = mesh;
+
+			scope.meshBody.clipOffset = 0;
+			scope.activeAnimationClipName = mesh.geometry.animations[0].name;
+
+			scope.mixer = new THREE.AnimationMixer( mesh );
+
+			checkLoadingComplete();
+
+		} );
+
+		// WEAPONS
+
+		var generateCallback = function ( index, name ) {
+
+			return function( geo ) {
+
+				var mesh = createPart( geo, scope.skinsWeapon[ index ] );
+				mesh.scale.set( scope.scale, scope.scale, scope.scale );
+				mesh.visible = false;
+
+				mesh.name = name;
+
+				scope.root.add( mesh );
+
+				scope.weapons[ index ] = mesh;
+				scope.meshWeapon = mesh;
+
+				checkLoadingComplete();
+
+			}
+
+		};
+
+		for ( var i = 0; i < config.weapons.length; i ++ ) {
+
+			loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
+
+		}
+
+	};
+
+	this.setPlaybackRate = function ( rate ) {
+
+		if( rate !== 0 ) {
+			this.mixer.timeScale = 1 / rate;
+		}
+		else {
+			this.mixer.timeScale = 0;
+		}
+
+	};
+
+	this.setWireframe = function ( wireframeEnabled ) {
+
+		if ( wireframeEnabled ) {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
+
+		} else {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
+
+		}
+
+	};
+
+	this.setSkin = function( index ) {
+
+		if ( this.meshBody && this.meshBody.material.wireframe === false ) {
+
+			this.meshBody.material.map = this.skinsBody[ index ];
+
+		}
+
+	};
+
+	this.setWeapon = function ( index ) {
+
+		for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
+
+		var activeWeapon = this.weapons[ index ];
+
+		if ( activeWeapon ) {
+
+			activeWeapon.visible = true;
+			this.meshWeapon = activeWeapon;
+
+			scope.syncWeaponAnimation();
+
+		}
+
+	};
+
+	this.setAnimation = function ( clipName ) {
+
+		if ( this.meshBody ) {
+
+			if( this.meshBody.activeAction ) {
+				this.meshBody.activeAction.stop();
+				this.meshBody.activeAction = null;
+			}
+
+			var action = this.mixer.clipAction( clipName, this.meshBody );
+			if( action ) {
+
+				this.meshBody.activeAction = action.play();
+
+			}
+
+		}
+
+		scope.activeClipName = clipName;
+
+		scope.syncWeaponAnimation();
+
+	};
+
+	this.syncWeaponAnimation = function() {
+
+		var clipName = scope.activeClipName;
+
+		if ( scope.meshWeapon ) {
+
+			if( this.meshWeapon.activeAction ) {
+				this.meshWeapon.activeAction.stop();
+				this.meshWeapon.activeAction = null;
+			}
+
+			var geometry = this.meshWeapon.geometry,
+				animations = geometry.animations;
+
+			var action = this.mixer.clipAction( clipName, this.meshWeapon );
+			if( action ) {
+
+				this.meshWeapon.activeAction =
+						action.syncWith( this.meshBody.activeAction ).play();
+
+			}
+
+		}
+
+	}
+
+	this.update = function ( delta ) {
+
+		if( this.mixer ) this.mixer.update( delta );
+
+	};
+
+	function loadTextures( baseUrl, textureUrls ) {
+
+		var textureLoader = new THREE.TextureLoader();
+		var textures = [];
+
+		for ( var i = 0; i < textureUrls.length; i ++ ) {
+
+			textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
+			textures[ i ].mapping = THREE.UVMapping;
+			textures[ i ].name = textureUrls[ i ];
+
+		}
+
+		return textures;
+
+	}
+
+	function createPart( geometry, skinMap ) {
+
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
+
+		//
+
+		var mesh = new THREE.Mesh( geometry, materialTexture );
+		mesh.rotation.y = - Math.PI / 2;
+
+		mesh.castShadow = true;
+		mesh.receiveShadow = true;
+
+		//
+
+		mesh.materialTexture = materialTexture;
+		mesh.materialWireframe = materialWireframe;
+
+		return mesh;
+
+	}
+
+	function checkLoadingComplete() {
+
+		scope.loadCounter -= 1;
+
+		if ( scope.loadCounter === 0 ) scope.onLoadComplete();
+
+	}
+
+};

+ 560 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MD2CharacterComplex.js

@@ -0,0 +1,560 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MD2CharacterComplex = function () {
+
+	var scope = this;
+
+	this.scale = 1;
+
+	// animation parameters
+
+	this.animationFPS = 6;
+	this.transitionFrames = 15;
+
+	// movement model parameters
+
+	this.maxSpeed = 275;
+	this.maxReverseSpeed = - 275;
+
+	this.frontAcceleration = 600;
+	this.backAcceleration = 600;
+
+	this.frontDecceleration = 600;
+
+	this.angularSpeed = 2.5;
+
+	// rig
+
+	this.root = new THREE.Object3D();
+
+	this.meshBody = null;
+	this.meshWeapon = null;
+
+	this.controls = null;
+
+	// skins
+
+	this.skinsBody = [];
+	this.skinsWeapon = [];
+
+	this.weapons = [];
+
+	this.currentSkin = undefined;
+
+	//
+
+	this.onLoadComplete = function () {};
+
+	// internals
+
+	this.meshes = [];
+	this.animations = {};
+
+	this.loadCounter = 0;
+
+	// internal movement control variables
+
+	this.speed = 0;
+	this.bodyOrientation = 0;
+
+	this.walkSpeed = this.maxSpeed;
+	this.crouchSpeed = this.maxSpeed * 0.5;
+
+	// internal animation parameters
+
+	this.activeAnimation = null;
+	this.oldAnimation = null;
+
+	// API
+
+	this.enableShadows = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].castShadow = enable;
+			this.meshes[ i ].receiveShadow = enable;
+
+		}
+
+	};
+
+	this.setVisible = function ( enable ) {
+
+		for ( var i = 0; i < this.meshes.length; i ++ ) {
+
+			this.meshes[ i ].visible = enable;
+			this.meshes[ i ].visible = enable;
+
+		}
+
+	};
+
+
+	this.shareParts = function ( original ) {
+
+		this.animations = original.animations;
+		this.walkSpeed = original.walkSpeed;
+		this.crouchSpeed = original.crouchSpeed;
+
+		this.skinsBody = original.skinsBody;
+		this.skinsWeapon = original.skinsWeapon;
+
+		// BODY
+
+		var mesh = createPart( original.meshBody.geometry, this.skinsBody[ 0 ] );
+		mesh.scale.set( this.scale, this.scale, this.scale );
+
+		this.root.position.y = original.root.position.y;
+		this.root.add( mesh );
+
+		this.meshBody = mesh;
+
+		this.meshes.push( mesh );
+
+		// WEAPONS
+
+		for ( var i = 0; i < original.weapons.length; i ++ ) {
+
+			var meshWeapon = createPart( original.weapons[ i ].geometry, this.skinsWeapon[ i ] );
+			meshWeapon.scale.set( this.scale, this.scale, this.scale );
+			meshWeapon.visible = false;
+
+			meshWeapon.name = original.weapons[ i ].name;
+
+			this.root.add( meshWeapon );
+
+			this.weapons[ i ] = meshWeapon;
+			this.meshWeapon = meshWeapon;
+
+			this.meshes.push( meshWeapon );
+
+		}
+
+	};
+
+	this.loadParts = function ( config ) {
+
+		this.animations = config.animations;
+		this.walkSpeed = config.walkSpeed;
+		this.crouchSpeed = config.crouchSpeed;
+
+		this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
+
+		var weaponsTextures = [];
+		for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
+
+		// SKINS
+
+		this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
+		this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
+
+		// BODY
+
+		var loader = new THREE.MD2Loader();
+
+		loader.load( config.baseUrl + config.body, function( geo ) {
+
+			geo.computeBoundingBox();
+			scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
+
+			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
+			mesh.scale.set( scope.scale, scope.scale, scope.scale );
+
+			scope.root.add( mesh );
+
+			scope.meshBody = mesh;
+			scope.meshes.push( mesh );
+
+			checkLoadingComplete();
+
+		} );
+
+		// WEAPONS
+
+		var generateCallback = function ( index, name ) {
+
+			return function( geo ) {
+
+				var mesh = createPart( geo, scope.skinsWeapon[ index ] );
+				mesh.scale.set( scope.scale, scope.scale, scope.scale );
+				mesh.visible = false;
+
+				mesh.name = name;
+
+				scope.root.add( mesh );
+
+				scope.weapons[ index ] = mesh;
+				scope.meshWeapon = mesh;
+				scope.meshes.push( mesh );
+
+				checkLoadingComplete();
+
+			}
+
+		};
+
+		for ( var i = 0; i < config.weapons.length; i ++ ) {
+
+			loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
+
+		}
+
+	};
+
+	this.setPlaybackRate = function ( rate ) {
+
+		if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
+		if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
+
+	};
+
+	this.setWireframe = function ( wireframeEnabled ) {
+
+		if ( wireframeEnabled ) {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
+
+		} else {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
+
+		}
+
+	};
+
+	this.setSkin = function( index ) {
+
+		if ( this.meshBody && this.meshBody.material.wireframe === false ) {
+
+			this.meshBody.material.map = this.skinsBody[ index ];
+			this.currentSkin = index;
+
+		}
+
+	};
+
+	this.setWeapon = function ( index ) {
+
+		for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
+
+		var activeWeapon = this.weapons[ index ];
+
+		if ( activeWeapon ) {
+
+			activeWeapon.visible = true;
+			this.meshWeapon = activeWeapon;
+
+			if ( this.activeAnimation ) {
+
+				activeWeapon.playAnimation( this.activeAnimation );
+				this.meshWeapon.setAnimationTime( this.activeAnimation, this.meshBody.getAnimationTime( this.activeAnimation ) );
+
+			}
+
+		}
+
+	};
+
+	this.setAnimation = function ( animationName ) {
+
+		if ( animationName === this.activeAnimation || ! animationName ) return;
+
+		if ( this.meshBody ) {
+
+			this.meshBody.setAnimationWeight( animationName, 0 );
+			this.meshBody.playAnimation( animationName );
+
+			this.oldAnimation = this.activeAnimation;
+			this.activeAnimation = animationName;
+
+			this.blendCounter = this.transitionFrames;
+
+		}
+
+		if ( this.meshWeapon ) {
+
+			this.meshWeapon.setAnimationWeight( animationName, 0 );
+			this.meshWeapon.playAnimation( animationName );
+
+		}
+
+
+	};
+
+	this.update = function ( delta ) {
+
+		if ( this.controls ) this.updateMovementModel( delta );
+
+		if ( this.animations ) {
+
+			this.updateBehaviors( delta );
+			this.updateAnimations( delta );
+
+		}
+
+	};
+
+	this.updateAnimations = function ( delta ) {
+
+		var mix = 1;
+
+		if ( this.blendCounter > 0 ) {
+
+			mix = ( this.transitionFrames - this.blendCounter ) / this.transitionFrames;
+			this.blendCounter -= 1;
+
+		}
+
+		if ( this.meshBody ) {
+
+			this.meshBody.update( delta );
+
+			this.meshBody.setAnimationWeight( this.activeAnimation, mix );
+			this.meshBody.setAnimationWeight( this.oldAnimation,  1 - mix );
+
+		}
+
+		if ( this.meshWeapon ) {
+
+			this.meshWeapon.update( delta );
+
+			this.meshWeapon.setAnimationWeight( this.activeAnimation, mix );
+			this.meshWeapon.setAnimationWeight( this.oldAnimation,  1 - mix );
+
+		}
+
+	};
+
+	this.updateBehaviors = function ( delta ) {
+
+		var controls = this.controls;
+		var animations = this.animations;
+
+		var moveAnimation, idleAnimation;
+
+		// crouch vs stand
+
+		if ( controls.crouch ) {
+
+			moveAnimation = animations[ "crouchMove" ];
+			idleAnimation = animations[ "crouchIdle" ];
+
+		} else {
+
+			moveAnimation = animations[ "move" ];
+			idleAnimation = animations[ "idle" ];
+
+		}
+
+		// actions
+
+		if ( controls.jump ) {
+
+			moveAnimation = animations[ "jump" ];
+			idleAnimation = animations[ "jump" ];
+
+		}
+
+		if ( controls.attack ) {
+
+			if ( controls.crouch ) {
+
+				moveAnimation = animations[ "crouchAttack" ];
+				idleAnimation = animations[ "crouchAttack" ];
+
+			} else {
+
+				moveAnimation = animations[ "attack" ];
+				idleAnimation = animations[ "attack" ];
+
+			}
+
+		}
+
+		// set animations
+
+		if ( controls.moveForward || controls.moveBackward || controls.moveLeft || controls.moveRight ) {
+
+			if ( this.activeAnimation !== moveAnimation ) {
+
+				this.setAnimation( moveAnimation );
+
+			}
+
+		}
+
+
+		if ( Math.abs( this.speed ) < 0.2 * this.maxSpeed && ! ( controls.moveLeft || controls.moveRight || controls.moveForward || controls.moveBackward ) ) {
+
+			if ( this.activeAnimation !== idleAnimation ) {
+
+				this.setAnimation( idleAnimation );
+
+			}
+
+		}
+
+		// set animation direction
+
+		if ( controls.moveForward ) {
+
+			if ( this.meshBody ) {
+
+				this.meshBody.setAnimationDirectionForward( this.activeAnimation );
+				this.meshBody.setAnimationDirectionForward( this.oldAnimation );
+
+			}
+
+			if ( this.meshWeapon ) {
+
+				this.meshWeapon.setAnimationDirectionForward( this.activeAnimation );
+				this.meshWeapon.setAnimationDirectionForward( this.oldAnimation );
+
+			}
+
+		}
+
+		if ( controls.moveBackward ) {
+
+			if ( this.meshBody ) {
+
+				this.meshBody.setAnimationDirectionBackward( this.activeAnimation );
+				this.meshBody.setAnimationDirectionBackward( this.oldAnimation );
+
+			}
+
+			if ( this.meshWeapon ) {
+
+				this.meshWeapon.setAnimationDirectionBackward( this.activeAnimation );
+				this.meshWeapon.setAnimationDirectionBackward( this.oldAnimation );
+
+			}
+
+		}
+
+	};
+
+	this.updateMovementModel = function ( delta ) {
+
+		var controls = this.controls;
+
+		// speed based on controls
+
+		if ( controls.crouch ) 	this.maxSpeed = this.crouchSpeed;
+		else this.maxSpeed = this.walkSpeed;
+
+		this.maxReverseSpeed = - this.maxSpeed;
+
+		if ( controls.moveForward )  this.speed = THREE.Math.clamp( this.speed + delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+		if ( controls.moveBackward ) this.speed = THREE.Math.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		// orientation based on controls
+		// (don't just stand while turning)
+
+		var dir = 1;
+
+		if ( controls.moveLeft ) {
+
+			this.bodyOrientation += delta * this.angularSpeed;
+			this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		}
+
+		if ( controls.moveRight ) {
+
+			this.bodyOrientation -= delta * this.angularSpeed;
+			this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		}
+
+		// speed decay
+
+		if ( ! ( controls.moveForward || controls.moveBackward ) ) {
+
+			if ( this.speed > 0 ) {
+
+				var k = exponentialEaseOut( this.speed / this.maxSpeed );
+				this.speed = THREE.Math.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed );
+
+			} else {
+
+				var k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
+				this.speed = THREE.Math.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 );
+
+			}
+
+		}
+
+		// displacement
+
+		var forwardDelta = this.speed * delta;
+
+		this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta;
+		this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta;
+
+		// steering
+
+		this.root.rotation.y = this.bodyOrientation;
+
+	};
+
+	// internal helpers
+
+	function loadTextures( baseUrl, textureUrls ) {
+
+		var textureLoader = new THREE.TextureLoader();
+		var textures = [];
+
+		for ( var i = 0; i < textureUrls.length; i ++ ) {
+
+			textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], checkLoadingComplete );
+			textures[ i ].mapping = THREE.UVMapping;
+			textures[ i ].name = textureUrls[ i ];
+
+		}
+
+		return textures;
+
+	}
+
+	function createPart( geometry, skinMap ) {
+
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, map: skinMap, morphTargets: true, morphNormals: true } );
+
+		//
+
+		var mesh = new THREE.MorphBlendMesh( geometry, materialTexture );
+		mesh.rotation.y = - Math.PI / 2;
+
+		//
+
+		mesh.materialTexture = materialTexture;
+		mesh.materialWireframe = materialWireframe;
+
+		//
+
+		mesh.autoCreateAnimations( scope.animationFPS );
+
+		return mesh;
+
+	}
+
+	function checkLoadingComplete() {
+
+		scope.loadCounter -= 1;
+		if ( scope.loadCounter === 0 ) 	scope.onLoadComplete();
+
+	}
+
+	function exponentialEaseOut( k ) {
+
+		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
+
+	}
+
+};

+ 1044 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MarchingCubes.js

@@ -0,0 +1,1044 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @author mrdoob / http://mrdoob.com
+ * Port of http://webglsamples.org/blob/blob.html
+ */
+
+THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors ) {
+
+	THREE.ImmediateRenderObject.call( this, material );
+
+	var scope = this;
+
+	// temp buffers used in polygonize
+
+	var vlist = new Float32Array( 12 * 3 );
+	var nlist = new Float32Array( 12 * 3 );
+
+	this.enableUvs = enableUvs !== undefined ? enableUvs : false;
+	this.enableColors = enableColors !== undefined ? enableColors : false;
+
+	// functions have to be object properties
+	// prototype functions kill performance
+	// (tested and it was 4x slower !!!)
+
+	this.init = function ( resolution ) {
+
+		this.resolution = resolution;
+
+		// parameters
+
+		this.isolation = 80.0;
+
+		// size of field, 32 is pushing it in Javascript :)
+
+		this.size = resolution;
+		this.size2 = this.size * this.size;
+		this.size3 = this.size2 * this.size;
+		this.halfsize = this.size / 2.0;
+
+		// deltas
+
+		this.delta = 2.0 / this.size;
+		this.yd = this.size;
+		this.zd = this.size2;
+
+		this.field = new Float32Array( this.size3 );
+		this.normal_cache = new Float32Array( this.size3 * 3 );
+
+		// immediate render mode simulator
+
+		this.maxCount = 4096; // TODO: find the fastest size for this buffer
+		this.count = 0;
+
+		this.hasPositions = false;
+		this.hasNormals = false;
+		this.hasColors = false;
+		this.hasUvs = false;
+
+		this.positionArray = new Float32Array( this.maxCount * 3 );
+		this.normalArray   = new Float32Array( this.maxCount * 3 );
+
+		if ( this.enableUvs ) {
+
+			this.uvArray = new Float32Array( this.maxCount * 2 );
+
+		}
+
+		if ( this.enableColors ) {
+
+			this.colorArray   = new Float32Array( this.maxCount * 3 );
+
+		}
+
+	};
+
+	///////////////////////
+	// Polygonization
+	///////////////////////
+
+	function lerp( a, b, t ) {
+
+		return a + ( b - a ) * t;
+
+	}
+
+	function VIntX( q, offset, isol, x, y, z, valp1, valp2 ) {
+
+		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
+		nc = scope.normal_cache;
+
+		vlist[ offset + 0 ] = x + mu * scope.delta;
+		vlist[ offset + 1 ] = y;
+		vlist[ offset + 2 ] = z;
+
+		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q + 3 ], mu );
+		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu );
+		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu );
+
+	}
+
+	function VIntY( q, offset, isol, x, y, z, valp1, valp2 ) {
+
+		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
+		nc = scope.normal_cache;
+
+		vlist[ offset + 0 ] = x;
+		vlist[ offset + 1 ] = y + mu * scope.delta;
+		vlist[ offset + 2 ] = z;
+
+		var q2 = q + scope.yd * 3;
+
+		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
+		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
+		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
+
+	}
+
+	function VIntZ( q, offset, isol, x, y, z, valp1, valp2 ) {
+
+		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
+		nc = scope.normal_cache;
+
+		vlist[ offset + 0 ] = x;
+		vlist[ offset + 1 ] = y;
+		vlist[ offset + 2 ] = z + mu * scope.delta;
+
+		var q2 = q + scope.zd * 3;
+
+		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
+		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
+		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
+
+	}
+
+	function compNorm( q ) {
+
+		var q3 = q * 3;
+
+		if ( scope.normal_cache[ q3 ] === 0.0 ) {
+
+			scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] 	    - scope.field[ q + 1 ];
+			scope.normal_cache[ q3 + 1 ] = scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ];
+			scope.normal_cache[ q3 + 2 ] = scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ];
+
+		}
+
+	}
+
+	// Returns total number of triangles. Fills triangles.
+	// (this is where most of time is spent - it's inner work of O(n3) loop )
+
+	function polygonize( fx, fy, fz, q, isol, renderCallback ) {
+
+		// cache indices
+		var q1 = q + 1,
+			qy = q + scope.yd,
+			qz = q + scope.zd,
+			q1y = q1 + scope.yd,
+			q1z = q1 + scope.zd,
+			qyz = q + scope.yd + scope.zd,
+			q1yz = q1 + scope.yd + scope.zd;
+
+		var cubeindex = 0,
+			field0 = scope.field[ q ],
+			field1 = scope.field[ q1 ],
+			field2 = scope.field[ qy ],
+			field3 = scope.field[ q1y ],
+			field4 = scope.field[ qz ],
+			field5 = scope.field[ q1z ],
+			field6 = scope.field[ qyz ],
+			field7 = scope.field[ q1yz ];
+
+		if ( field0 < isol ) cubeindex |= 1;
+		if ( field1 < isol ) cubeindex |= 2;
+		if ( field2 < isol ) cubeindex |= 8;
+		if ( field3 < isol ) cubeindex |= 4;
+		if ( field4 < isol ) cubeindex |= 16;
+		if ( field5 < isol ) cubeindex |= 32;
+		if ( field6 < isol ) cubeindex |= 128;
+		if ( field7 < isol ) cubeindex |= 64;
+
+		// if cube is entirely in/out of the surface - bail, nothing to draw
+
+		var bits = THREE.edgeTable[ cubeindex ];
+		if ( bits === 0 ) return 0;
+
+		var d = scope.delta,
+			fx2 = fx + d,
+			fy2 = fy + d,
+			fz2 = fz + d;
+
+		// top of the cube
+
+		if ( bits & 1 ) {
+
+			compNorm( q );
+			compNorm( q1 );
+			VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1 );
+
+		}
+
+		if ( bits & 2 ) {
+
+			compNorm( q1 );
+			compNorm( q1y );
+			VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3 );
+
+		}
+
+		if ( bits & 4 ) {
+
+			compNorm( qy );
+			compNorm( q1y );
+			VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3 );
+
+		}
+
+		if ( bits & 8 ) {
+
+			compNorm( q );
+			compNorm( qy );
+			VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2 );
+
+		}
+
+		// bottom of the cube
+
+		if ( bits & 16 ) {
+
+			compNorm( qz );
+			compNorm( q1z );
+			VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5 );
+
+		}
+
+		if ( bits & 32 ) {
+
+			compNorm( q1z );
+			compNorm( q1yz );
+			VIntY( q1z * 3, 15, isol, fx2, fy, fz2, field5, field7 );
+
+		}
+
+		if ( bits & 64 ) {
+
+			compNorm( qyz );
+			compNorm( q1yz );
+			VIntX( qyz * 3, 18, isol, fx, fy2, fz2, field6, field7 );
+
+		}
+
+		if ( bits & 128 ) {
+
+			compNorm( qz );
+			compNorm( qyz );
+			VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6 );
+
+		}
+
+		// vertical lines of the cube
+
+		if ( bits & 256 ) {
+
+			compNorm( q );
+			compNorm( qz );
+			VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4 );
+
+		}
+
+		if ( bits & 512 ) {
+
+			compNorm( q1 );
+			compNorm( q1z );
+			VIntZ( q1 * 3, 27, isol, fx2, fy,  fz, field1, field5 );
+
+		}
+
+		if ( bits & 1024 ) {
+
+			compNorm( q1y );
+			compNorm( q1yz );
+			VIntZ( q1y * 3, 30, isol, fx2, fy2, fz, field3, field7 );
+
+		}
+
+		if ( bits & 2048 ) {
+
+			compNorm( qy );
+			compNorm( qyz );
+			VIntZ( qy * 3, 33, isol, fx,  fy2, fz, field2, field6 );
+
+		}
+
+		cubeindex <<= 4;  // re-purpose cubeindex into an offset into triTable
+
+		var o1, o2, o3, numtris = 0, i = 0;
+
+		// here is where triangles are created
+
+		while ( THREE.triTable[ cubeindex + i ] != - 1 ) {
+
+			o1 = cubeindex + i;
+			o2 = o1 + 1;
+			o3 = o1 + 2;
+
+			posnormtriv( vlist, nlist,
+				3 * THREE.triTable[ o1 ],
+				3 * THREE.triTable[ o2 ],
+				3 * THREE.triTable[ o3 ],
+				renderCallback );
+
+			i += 3;
+			numtris ++;
+
+		}
+
+		return numtris;
+
+	}
+
+	/////////////////////////////////////
+	// Immediate render mode simulator
+	/////////////////////////////////////
+
+	function posnormtriv( pos, norm, o1, o2, o3, renderCallback ) {
+
+		var c = scope.count * 3;
+
+		// positions
+
+		scope.positionArray[ c + 0 ] = pos[ o1 ];
+		scope.positionArray[ c + 1 ] = pos[ o1 + 1 ];
+		scope.positionArray[ c + 2 ] = pos[ o1 + 2 ];
+
+		scope.positionArray[ c + 3 ] = pos[ o2 ];
+		scope.positionArray[ c + 4 ] = pos[ o2 + 1 ];
+		scope.positionArray[ c + 5 ] = pos[ o2 + 2 ];
+
+		scope.positionArray[ c + 6 ] = pos[ o3 ];
+		scope.positionArray[ c + 7 ] = pos[ o3 + 1 ];
+		scope.positionArray[ c + 8 ] = pos[ o3 + 2 ];
+
+		// normals
+
+		scope.normalArray[ c + 0 ] = norm[ o1 ];
+		scope.normalArray[ c + 1 ] = norm[ o1 + 1 ];
+		scope.normalArray[ c + 2 ] = norm[ o1 + 2 ];
+
+		scope.normalArray[ c + 3 ] = norm[ o2 ];
+		scope.normalArray[ c + 4 ] = norm[ o2 + 1 ];
+		scope.normalArray[ c + 5 ] = norm[ o2 + 2 ];
+
+		scope.normalArray[ c + 6 ] = norm[ o3 ];
+		scope.normalArray[ c + 7 ] = norm[ o3 + 1 ];
+		scope.normalArray[ c + 8 ] = norm[ o3 + 2 ];
+
+		// uvs
+
+		if ( scope.enableUvs ) {
+
+			var d = scope.count * 2;
+
+			scope.uvArray[ d + 0 ] = pos[ o1 ];
+			scope.uvArray[ d + 1 ] = pos[ o1 + 2 ];
+
+			scope.uvArray[ d + 2 ] = pos[ o2 ];
+			scope.uvArray[ d + 3 ] = pos[ o2 + 2 ];
+
+			scope.uvArray[ d + 4 ] = pos[ o3 ];
+			scope.uvArray[ d + 5 ] = pos[ o3 + 2 ];
+
+		}
+
+		// colors
+
+		if ( scope.enableColors ) {
+
+			scope.colorArray[ c + 0 ] = pos[ o1 ];
+			scope.colorArray[ c + 1 ] = pos[ o1 + 1 ];
+			scope.colorArray[ c + 2 ] = pos[ o1 + 2 ];
+
+			scope.colorArray[ c + 3 ] = pos[ o2 ];
+			scope.colorArray[ c + 4 ] = pos[ o2 + 1 ];
+			scope.colorArray[ c + 5 ] = pos[ o2 + 2 ];
+
+			scope.colorArray[ c + 6 ] = pos[ o3 ];
+			scope.colorArray[ c + 7 ] = pos[ o3 + 1 ];
+			scope.colorArray[ c + 8 ] = pos[ o3 + 2 ];
+
+		}
+
+		scope.count += 3;
+
+		if ( scope.count >= scope.maxCount - 3 ) {
+
+			scope.hasPositions = true;
+			scope.hasNormals = true;
+
+			if ( scope.enableUvs ) {
+
+				scope.hasUvs = true;
+
+			}
+
+			if ( scope.enableColors ) {
+
+				scope.hasColors = true;
+
+			}
+
+			renderCallback( scope );
+
+		}
+
+	}
+
+	this.begin = function () {
+
+		this.count = 0;
+
+		this.hasPositions = false;
+		this.hasNormals = false;
+		this.hasUvs = false;
+		this.hasColors = false;
+
+	};
+
+	this.end = function ( renderCallback ) {
+
+		if ( this.count === 0 ) return;
+
+		for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) {
+
+			this.positionArray[ i ] = 0.0;
+
+		}
+
+		this.hasPositions = true;
+		this.hasNormals = true;
+
+		if ( this.enableUvs ) {
+
+			this.hasUvs = true;
+
+		}
+
+		if ( this.enableColors ) {
+
+			this.hasColors = true;
+
+		}
+
+		renderCallback( this );
+
+	};
+
+	/////////////////////////////////////
+	// Metaballs
+	/////////////////////////////////////
+
+	// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
+	// a fixed distance, determined by strength and subtract.
+
+	this.addBall = function ( ballx, bally, ballz, strength, subtract ) {
+
+		var sign = Math.sign( strength );
+		strength = Math.abs( strength );
+
+		// Let's solve the equation to find the radius:
+		// 1.0 / (0.000001 + radius^2) * strength - subtract = 0
+		// strength / (radius^2) = subtract
+		// strength = subtract * radius^2
+		// radius^2 = strength / subtract
+		// radius = sqrt(strength / subtract)
+
+		var radius = this.size * Math.sqrt( strength / subtract ),
+			zs = ballz * this.size,
+			ys = bally * this.size,
+			xs = ballx * this.size;
+
+		var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1;
+		var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1;
+		var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1;
+		var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1;
+		var min_x = Math.floor( xs - radius ); if ( min_x < 1  ) min_x = 1;
+		var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1;
+
+
+		// Don't polygonize in the outer layer because normals aren't
+		// well-defined there.
+
+		var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val;
+
+		for ( z = min_z; z < max_z; z ++ ) {
+
+			z_offset = this.size2 * z;
+			fz = z / this.size - ballz;
+			fz2 = fz * fz;
+
+			for ( y = min_y; y < max_y; y ++ ) {
+
+				y_offset = z_offset + this.size * y;
+				fy = y / this.size - bally;
+				fy2 = fy * fy;
+
+				for ( x = min_x; x < max_x; x ++ ) {
+
+					fx = x / this.size - ballx;
+					val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract;
+					if ( val > 0.0 ) this.field[ y_offset + x ] += val * sign;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	this.addPlaneX = function( strength, subtract ) {
+
+		var x, y, z, xx, val, xdiv, cxy,
+
+			// cache attribute lookups
+			size = this.size,
+			yd = this.yd,
+			zd = this.zd,
+			field = this.field,
+
+			dist = size * Math.sqrt( strength / subtract );
+
+		if ( dist > size ) dist = size;
+
+		for ( x = 0; x < dist; x ++ ) {
+
+			xdiv = x / size;
+			xx = xdiv * xdiv;
+			val = strength / ( 0.0001 + xx ) - subtract;
+
+			if ( val > 0.0 ) {
+
+				for ( y = 0; y < size; y ++ ) {
+
+					cxy = x + y * yd;
+
+					for ( z = 0; z < size; z ++ ) {
+
+						field[ zd * z + cxy ] += val;
+
+					}
+
+				}
+
+			}
+
+		}
+
+	};
+
+	this.addPlaneY = function( strength, subtract ) {
+
+		var x, y, z, yy, val, ydiv, cy, cxy,
+
+			// cache attribute lookups
+			size = this.size,
+			yd = this.yd,
+			zd = this.zd,
+			field = this.field,
+
+			dist = size * Math.sqrt( strength / subtract );
+
+		if ( dist > size ) dist = size;
+
+		for ( y = 0; y < dist; y ++ ) {
+
+			ydiv = y / size;
+			yy = ydiv * ydiv;
+			val = strength / ( 0.0001 + yy ) - subtract;
+
+			if ( val > 0.0 ) {
+
+				cy = y * yd;
+
+				for ( x = 0; x < size; x ++ ) {
+
+					cxy = cy + x;
+
+					for ( z = 0; z < size; z ++ )
+						field[ zd * z + cxy ] += val;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	this.addPlaneZ = function( strength, subtract ) {
+
+		var x, y, z, zz, val, zdiv, cz, cyz,
+
+			// cache attribute lookups
+			size = this.size,
+			yd = this.yd,
+			zd = this.zd,
+			field = this.field,
+
+			dist = size * Math.sqrt( strength / subtract );
+
+		if ( dist > size ) dist = size;
+
+		for ( z = 0; z < dist; z ++ ) {
+
+			zdiv = z / size;
+			zz = zdiv * zdiv;
+			val = strength / ( 0.0001 + zz ) - subtract;
+			if ( val > 0.0 ) {
+
+				cz = zd * z;
+
+				for ( y = 0; y < size; y ++ ) {
+
+					cyz = cz + y * yd;
+
+					for ( x = 0; x < size; x ++ )
+						field[ cyz + x ] += val;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	/////////////////////////////////////
+	// Updates
+	/////////////////////////////////////
+
+	this.reset = function () {
+
+		var i;
+
+		// wipe the normal cache
+
+		for ( i = 0; i < this.size3; i ++ ) {
+
+			this.normal_cache[ i * 3 ] = 0.0;
+			this.field[ i ] = 0.0;
+
+		}
+
+	};
+
+	this.render = function ( renderCallback ) {
+
+		this.begin();
+
+		// Triangulate. Yeah, this is slow.
+
+		var smin2 = this.size - 2;
+
+		for ( var z = 1; z < smin2; z ++ ) {
+
+			var z_offset = this.size2 * z;
+			var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
+
+			for ( var y = 1; y < smin2; y ++ ) {
+
+				var y_offset = z_offset + this.size * y;
+				var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
+
+				for ( var x = 1; x < smin2; x ++ ) {
+
+					var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
+					var q = y_offset + x;
+
+					polygonize( fx, fy, fz, q, this.isolation, renderCallback );
+
+				}
+
+			}
+
+		}
+
+		this.end( renderCallback );
+
+	};
+
+	this.generateGeometry = function() {
+
+		var start = 0, geo = new THREE.Geometry();
+		var normals = [];
+
+		var geo_callback = function( object ) {
+
+			for ( var i = 0; i < object.count; i ++ ) {
+
+				var vertex = new THREE.Vector3().fromArray( object.positionArray, i * 3 );
+				var normal = new THREE.Vector3().fromArray( object.normalArray, i * 3 );
+
+				geo.vertices.push( vertex );
+				normals.push( normal );
+
+			}
+
+			var nfaces = object.count / 3;
+
+			for ( i = 0; i < nfaces; i ++ ) {
+
+				var a = ( start + i ) * 3;
+				var b = a + 1;
+				var c = a + 2;
+
+				var na = normals[ a ];
+				var nb = normals[ b ];
+				var nc = normals[ c ];
+
+				var face = new THREE.Face3( a, b, c, [ na, nb, nc ] );
+				geo.faces.push( face );
+
+			}
+
+			start += nfaces;
+			object.count = 0;
+
+		};
+
+		this.render( geo_callback );
+
+		// console.log( "generated " + geo.faces.length + " triangles" );
+
+		return geo;
+
+	};
+
+	this.init( resolution );
+
+};
+
+THREE.MarchingCubes.prototype = Object.create( THREE.ImmediateRenderObject.prototype );
+THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes;
+
+
+/////////////////////////////////////
+// Marching cubes lookup tables
+/////////////////////////////////////
+
+// These tables are straight from Paul Bourke's page:
+// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
+// who in turn got them from Cory Gene Bloyd.
+
+THREE.edgeTable = new Int32Array( [
+0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
+0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
+0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
+0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
+0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
+0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
+0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
+0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
+0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
+0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] );
+
+THREE.triTable = new Int32Array( [
+- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1,
+3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1,
+4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1,
+9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1,
+10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1,
+5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1,
+8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1,
+2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1,
+11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1,
+5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1,
+11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1,
+11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1,
+2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1,
+6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1,
+6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1,
+8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1,
+7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1,
+3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1,
+9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1,
+8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1,
+0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1,
+6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1,
+10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1,
+0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1,
+3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1,
+9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1,
+8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1,
+3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1,
+10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1,
+10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1,
+7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1,
+1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1,
+11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1,
+8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1,
+0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1,
+7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1,
+7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1,
+10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1,
+0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1,
+7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1,
+6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1,
+4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1,
+10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1,
+8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1,
+1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1,
+10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1,
+10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1,
+9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1,
+7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1,
+3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1,
+7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1,
+3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1,
+6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1,
+9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1,
+1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1,
+4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1,
+7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1,
+6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1,
+0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1,
+6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1,
+0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1,
+11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1,
+6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1,
+5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1,
+9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1,
+1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1,
+10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1,
+0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1,
+11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1,
+9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1,
+7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1,
+2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1,
+9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1,
+9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1,
+1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1,
+0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1,
+10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1,
+2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1,
+0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1,
+0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1,
+9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1,
+5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1,
+5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1,
+8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1,
+9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1,
+1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1,
+3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1,
+4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1,
+9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1,
+11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1,
+2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1,
+9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1,
+3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1,
+1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1,
+4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1,
+0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1,
+1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] );

+ 302 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Mirror.js

@@ -0,0 +1,302 @@
+/**
+ * @author Slayvin / http://slayvin.net
+ */
+
+THREE.ShaderLib[ 'mirror' ] = {
+
+	uniforms: {
+		"mirrorColor": { value: new THREE.Color( 0x7F7F7F ) },
+		"mirrorSampler": { value: null },
+		"textureMatrix" : { value: new THREE.Matrix4() }
+	},
+
+	vertexShader: [
+
+		"uniform mat4 textureMatrix;",
+
+		"varying vec4 mirrorCoord;",
+
+		"void main() {",
+
+			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+			"mirrorCoord = textureMatrix * worldPosition;",
+
+			"gl_Position = projectionMatrix * mvPosition;",
+
+		"}"
+
+	].join( "\n" ),
+
+	fragmentShader: [
+
+		"uniform vec3 mirrorColor;",
+		"uniform sampler2D mirrorSampler;",
+
+		"varying vec4 mirrorCoord;",
+
+		"float blendOverlay(float base, float blend) {",
+			"return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );",
+		"}",
+
+		"void main() {",
+
+			"vec4 color = texture2DProj(mirrorSampler, mirrorCoord);",
+			"color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b), 1.0);",
+
+			"gl_FragColor = color;",
+
+		"}"
+
+	].join( "\n" )
+
+};
+
+THREE.Mirror = function ( renderer, camera, options ) {
+
+	THREE.Object3D.call( this );
+
+	this.name = 'mirror_' + this.id;
+
+	options = options || {};
+
+	this.matrixNeedsUpdate = true;
+
+	var width = options.textureWidth !== undefined ? options.textureWidth : 512;
+	var height = options.textureHeight !== undefined ? options.textureHeight : 512;
+
+	this.clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
+
+	var mirrorColor = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
+
+	this.renderer = renderer;
+	this.mirrorPlane = new THREE.Plane();
+	this.normal = new THREE.Vector3( 0, 0, 1 );
+	this.mirrorWorldPosition = new THREE.Vector3();
+	this.cameraWorldPosition = new THREE.Vector3();
+	this.rotationMatrix = new THREE.Matrix4();
+	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
+	this.clipPlane = new THREE.Vector4();
+
+	// For debug only, show the normal and plane of the mirror
+	var debugMode = options.debugMode !== undefined ? options.debugMode : false;
+
+	if ( debugMode ) {
+
+		var arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, 0 ), 10, 0xffff80 );
+		var planeGeometry = new THREE.Geometry();
+		planeGeometry.vertices.push( new THREE.Vector3( - 10, - 10, 0 ) );
+		planeGeometry.vertices.push( new THREE.Vector3( 10, - 10, 0 ) );
+		planeGeometry.vertices.push( new THREE.Vector3( 10, 10, 0 ) );
+		planeGeometry.vertices.push( new THREE.Vector3( - 10, 10, 0 ) );
+		planeGeometry.vertices.push( planeGeometry.vertices[ 0 ] );
+		var plane = new THREE.Line( planeGeometry, new THREE.LineBasicMaterial( { color: 0xffff80 } ) );
+
+		this.add( arrow );
+		this.add( plane );
+
+	}
+
+	if ( camera instanceof THREE.PerspectiveCamera ) {
+
+		this.camera = camera;
+
+	} else {
+
+		this.camera = new THREE.PerspectiveCamera();
+		console.log( this.name + ': camera is not a Perspective Camera!' );
+
+	}
+
+	this.textureMatrix = new THREE.Matrix4();
+
+	this.mirrorCamera = this.camera.clone();
+	this.mirrorCamera.matrixAutoUpdate = true;
+
+	var parameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+
+	this.renderTarget = new THREE.WebGLRenderTarget( width, height, parameters );
+	this.renderTarget2 = new THREE.WebGLRenderTarget( width, height, parameters );
+
+	var mirrorShader = THREE.ShaderLib[ "mirror" ];
+	var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
+
+	this.material = new THREE.ShaderMaterial( {
+
+		fragmentShader: mirrorShader.fragmentShader,
+		vertexShader: mirrorShader.vertexShader,
+		uniforms: mirrorUniforms
+
+	} );
+
+	this.material.uniforms.mirrorSampler.value = this.renderTarget.texture;
+	this.material.uniforms.mirrorColor.value = mirrorColor;
+	this.material.uniforms.textureMatrix.value = this.textureMatrix;
+
+	if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
+
+		this.renderTarget.texture.generateMipmaps = false;
+		this.renderTarget2.texture.generateMipmaps = false;
+
+	}
+
+	this.updateTextureMatrix();
+	this.render();
+
+};
+
+THREE.Mirror.prototype = Object.create( THREE.Object3D.prototype );
+THREE.Mirror.prototype.constructor = THREE.Mirror;
+
+THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
+
+	// update the mirror matrix to mirror the current view
+	this.updateTextureMatrix();
+	this.matrixNeedsUpdate = false;
+
+	// set the camera of the other mirror so the mirrored view is the reference view
+	var tempCamera = otherMirror.camera;
+	otherMirror.camera = this.mirrorCamera;
+
+	// render the other mirror in temp texture
+	otherMirror.renderTemp();
+	otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget2.texture;
+
+	// render the current mirror
+	this.render();
+	this.matrixNeedsUpdate = true;
+
+	// restore material and camera of other mirror
+	otherMirror.material.uniforms.mirrorSampler.value = otherMirror.renderTarget.texture;
+	otherMirror.camera = tempCamera;
+
+	// restore texture matrix of other mirror
+	otherMirror.updateTextureMatrix();
+
+};
+
+THREE.Mirror.prototype.updateTextureMatrix = function () {
+
+	this.updateMatrixWorld();
+	this.camera.updateMatrixWorld();
+
+	this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
+	this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
+
+	this.rotationMatrix.extractRotation( this.matrixWorld );
+
+	this.normal.set( 0, 0, 1 );
+	this.normal.applyMatrix4( this.rotationMatrix );
+
+	var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
+	view.reflect( this.normal ).negate();
+	view.add( this.mirrorWorldPosition );
+
+	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
+
+	this.lookAtPosition.set( 0, 0, - 1 );
+	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
+	this.lookAtPosition.add( this.cameraWorldPosition );
+
+	var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
+	target.reflect( this.normal ).negate();
+	target.add( this.mirrorWorldPosition );
+
+	this.up.set( 0, - 1, 0 );
+	this.up.applyMatrix4( this.rotationMatrix );
+	this.up.reflect( this.normal ).negate();
+
+	this.mirrorCamera.position.copy( view );
+	this.mirrorCamera.up = this.up;
+	this.mirrorCamera.lookAt( target );
+
+	this.mirrorCamera.updateProjectionMatrix();
+	this.mirrorCamera.updateMatrixWorld();
+	this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld );
+
+	// Update the texture matrix
+	this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
+							0.0, 0.5, 0.0, 0.5,
+							0.0, 0.0, 0.5, 0.5,
+							0.0, 0.0, 0.0, 1.0 );
+	this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
+	this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse );
+
+	// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
+	// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
+	this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
+	this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
+
+	this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
+
+	var q = new THREE.Vector4();
+	var projectionMatrix = this.mirrorCamera.projectionMatrix;
+
+	q.x = ( Math.sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+	q.y = ( Math.sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+	q.z = - 1.0;
+	q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
+
+	// Calculate the scaled plane vector
+	var c = new THREE.Vector4();
+	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
+
+	// Replacing the third row of the projection matrix
+	projectionMatrix.elements[ 2 ] = c.x;
+	projectionMatrix.elements[ 6 ] = c.y;
+	projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
+	projectionMatrix.elements[ 14 ] = c.w;
+
+};
+
+THREE.Mirror.prototype.render = function () {
+
+	if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
+
+	this.matrixNeedsUpdate = true;
+
+	// Render the mirrored view of the current scene into the target texture
+	var scene = this;
+
+	while ( scene.parent !== null ) {
+
+		scene = scene.parent;
+
+	}
+
+	if ( scene !== undefined && scene instanceof THREE.Scene ) {
+
+		// We can't render ourself to ourself
+		var visible = this.material.visible;
+		this.material.visible = false;
+
+		this.renderer.render( scene, this.mirrorCamera, this.renderTarget, true );
+
+		this.material.visible = visible;
+
+	}
+
+};
+
+THREE.Mirror.prototype.renderTemp = function () {
+
+	if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
+
+	this.matrixNeedsUpdate = true;
+
+	// Render the mirrored view of the current scene into the target texture
+	var scene = this;
+
+	while ( scene.parent !== null ) {
+
+		scene = scene.parent;
+
+	}
+
+	if ( scene !== undefined && scene instanceof THREE.Scene ) {
+
+		this.renderer.render( scene, this.mirrorCamera, this.renderTarget2, true );
+
+	}
+
+};

+ 69 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MorphAnimMesh.js

@@ -0,0 +1,69 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MorphAnimMesh = function ( geometry, material ) {
+
+	THREE.Mesh.call( this, geometry, material );
+
+	this.type = 'MorphAnimMesh';
+
+	this.mixer = new THREE.AnimationMixer( this );
+	this.activeAction = null;
+};
+
+THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
+THREE.MorphAnimMesh.prototype.constructor = THREE.MorphAnimMesh;
+
+THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
+
+	this.mixer.timeScale = 1.0;
+
+};
+
+THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
+
+	this.mixer.timeScale = -1.0;
+
+};
+
+THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
+
+	if( this.activeAction ) {
+
+		this.activeAction.stop();
+		this.activeAction = null;
+		
+	}
+
+	var clip = THREE.AnimationClip.findByName( this, label );
+
+	if ( clip ) {
+
+		var action = this.mixer.clipAction( clip );
+		action.timeScale = ( clip.tracks.length * fps ) / clip.duration;
+		this.activeAction = action.play();
+
+	} else {
+
+		throw new Error( 'THREE.MorphAnimMesh: animations[' + label + '] undefined in .playAnimation()' );
+
+	}
+
+};
+
+THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
+
+	this.mixer.update( delta );
+
+};
+
+THREE.MorphAnimMesh.prototype.copy = function ( source ) {
+
+	THREE.Mesh.prototype.copy.call( this, source );
+
+	this.mixer = new THREE.AnimationMixer( this );
+
+	return this;
+
+};

+ 73 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/MorphAnimation.js

@@ -0,0 +1,73 @@
+/**
+ * @author mrdoob / http://mrdoob.com
+ * @author willy-vvu / http://willy-vvu.github.io
+ */
+
+THREE.MorphAnimation = function ( mesh ) {
+
+	this.mesh = mesh;
+	this.frames = mesh.morphTargetInfluences.length;
+	this.currentTime = 0;
+	this.duration = 1000;
+	this.loop = true;
+	this.lastFrame = 0;
+	this.currentFrame = 0;
+
+	this.isPlaying = false;
+
+};
+
+THREE.MorphAnimation.prototype = {
+
+	constructor: THREE.MorphAnimation,
+
+	play: function () {
+
+		this.isPlaying = true;
+
+	},
+
+	pause: function () {
+
+		this.isPlaying = false;
+
+	},
+
+	update: function ( delta ) {
+
+		if ( this.isPlaying === false ) return;
+
+		this.currentTime += delta;
+
+		if ( this.loop === true && this.currentTime > this.duration ) {
+
+			this.currentTime %= this.duration;
+
+		}
+
+		this.currentTime = Math.min( this.currentTime, this.duration );
+
+		var frameTime = this.duration / this.frames;
+		var frame = Math.floor( this.currentTime / frameTime );
+
+		var influences = this.mesh.morphTargetInfluences;
+
+		if ( frame !== this.currentFrame ) {
+
+			influences[ this.lastFrame ] = 0;
+			influences[ this.currentFrame ] = 1;
+			influences[ frame ] = 0;
+
+			this.lastFrame = this.currentFrame;
+			this.currentFrame = frame;
+
+		}
+
+		var mix = ( this.currentTime % frameTime ) / frameTime;
+
+		influences[ frame ] = mix;
+		influences[ this.lastFrame ] = 1 - mix;
+
+	}
+
+};

+ 359 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Ocean.js

@@ -0,0 +1,359 @@
+THREE.Ocean = function ( renderer, camera, scene, options ) {
+
+	// flag used to trigger parameter changes
+	this.changed = true;
+	this.initial = true;
+
+	// Assign required parameters as object properties
+	this.oceanCamera = new THREE.OrthographicCamera(); //camera.clone();
+	this.oceanCamera.position.z = 1;
+	this.renderer = renderer;
+	this.renderer.clearColor( 0xffffff );
+
+	this.scene = new THREE.Scene();
+
+	// Assign optional parameters as variables and object properties
+	function optionalParameter( value, defaultValue ) {
+
+		return value !== undefined ? value : defaultValue;
+
+	}
+	options = options || {};
+	this.clearColor = optionalParameter( options.CLEAR_COLOR, [ 1.0, 1.0, 1.0, 0.0 ] );
+	this.geometryOrigin = optionalParameter( options.GEOMETRY_ORIGIN, [ - 1000.0, - 1000.0 ] );
+	this.sunDirectionX = optionalParameter( options.SUN_DIRECTION[ 0 ], - 1.0 );
+	this.sunDirectionY = optionalParameter( options.SUN_DIRECTION[ 1 ], 1.0 );
+	this.sunDirectionZ = optionalParameter( options.SUN_DIRECTION[ 2 ], 1.0 );
+	this.oceanColor = optionalParameter( options.OCEAN_COLOR, new THREE.Vector3( 0.004, 0.016, 0.047 ) );
+	this.skyColor = optionalParameter( options.SKY_COLOR, new THREE.Vector3( 3.2, 9.6, 12.8 ) );
+	this.exposure = optionalParameter( options.EXPOSURE, 0.35 );
+	this.geometryResolution = optionalParameter( options.GEOMETRY_RESOLUTION, 32 );
+	this.geometrySize = optionalParameter( options.GEOMETRY_SIZE, 2000 );
+	this.resolution = optionalParameter( options.RESOLUTION, 64 );
+	this.floatSize = optionalParameter( options.SIZE_OF_FLOAT, 4 );
+	this.windX = optionalParameter( options.INITIAL_WIND[ 0 ], 10.0 );
+	this.windY = optionalParameter( options.INITIAL_WIND[ 1 ], 10.0 );
+	this.size = optionalParameter( options.INITIAL_SIZE, 250.0 );
+	this.choppiness = optionalParameter( options.INITIAL_CHOPPINESS, 1.5 );
+
+	//
+	this.matrixNeedsUpdate = false;
+
+	// Setup framebuffer pipeline
+	var renderTargetType = optionalParameter( options.USE_HALF_FLOAT, false ) ? THREE.HalfFloatType : THREE.FloatType;
+	var LinearClampParams = {
+		minFilter: THREE.LinearFilter,
+		magFilter: THREE.LinearFilter,
+		wrapS: THREE.ClampToEdgeWrapping,
+		wrapT: THREE.ClampToEdgeWrapping,
+		format: THREE.RGBAFormat,
+		stencilBuffer: false,
+		depthBuffer: false,
+		premultiplyAlpha: false,
+		type: renderTargetType
+	};
+	var NearestClampParams = {
+		minFilter: THREE.NearestFilter,
+		magFilter: THREE.NearestFilter,
+		wrapS: THREE.ClampToEdgeWrapping,
+		wrapT: THREE.ClampToEdgeWrapping,
+		format: THREE.RGBAFormat,
+		stencilBuffer: false,
+		depthBuffer: false,
+		premultiplyAlpha: false,
+		type: renderTargetType
+	};
+	var NearestRepeatParams = {
+		minFilter: THREE.NearestFilter,
+		magFilter: THREE.NearestFilter,
+		wrapS: THREE.RepeatWrapping,
+		wrapT: THREE.RepeatWrapping,
+		format: THREE.RGBAFormat,
+		stencilBuffer: false,
+		depthBuffer: false,
+		premultiplyAlpha: false,
+		type: renderTargetType
+	};
+	this.initialSpectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestRepeatParams );
+	this.spectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pingPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pongPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pingTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pongTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.displacementMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
+	this.normalMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
+
+	// Define shaders and constant uniforms
+	////////////////////////////////////////
+
+	// 0 - The vertex shader used in all of the simulation steps
+	var fullscreeenVertexShader = THREE.ShaderLib[ "ocean_sim_vertex" ];
+
+	// 1 - Horizontal wave vertices used for FFT
+	var oceanHorizontalShader = THREE.ShaderLib[ "ocean_subtransform" ];
+	var oceanHorizontalUniforms = THREE.UniformsUtils.clone( oceanHorizontalShader.uniforms );
+	this.materialOceanHorizontal = new THREE.ShaderMaterial( {
+		uniforms: oceanHorizontalUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: "#define HORIZONTAL \n" + oceanHorizontalShader.fragmentShader
+	} );
+	this.materialOceanHorizontal.uniforms.u_transformSize = { value: this.resolution };
+	this.materialOceanHorizontal.uniforms.u_subtransformSize = { value: null };
+	this.materialOceanHorizontal.uniforms.u_input = { value: null };
+	this.materialOceanHorizontal.depthTest = false;
+
+	// 2 - Vertical wave vertices used for FFT
+	var oceanVerticalShader = THREE.ShaderLib[ "ocean_subtransform" ];
+	var oceanVerticalUniforms = THREE.UniformsUtils.clone( oceanVerticalShader.uniforms );
+	this.materialOceanVertical = new THREE.ShaderMaterial( {
+		uniforms: oceanVerticalUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: oceanVerticalShader.fragmentShader
+	} );
+	this.materialOceanVertical.uniforms.u_transformSize = { value: this.resolution };
+	this.materialOceanVertical.uniforms.u_subtransformSize = { value: null };
+	this.materialOceanVertical.uniforms.u_input = { value: null };
+	this.materialOceanVertical.depthTest = false;
+
+	// 3 - Initial spectrum used to generate height map
+	var initialSpectrumShader = THREE.ShaderLib[ "ocean_initial_spectrum" ];
+	var initialSpectrumUniforms = THREE.UniformsUtils.clone( initialSpectrumShader.uniforms );
+	this.materialInitialSpectrum = new THREE.ShaderMaterial( {
+		uniforms: initialSpectrumUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: initialSpectrumShader.fragmentShader
+	} );
+	this.materialInitialSpectrum.uniforms.u_wind = { value: new THREE.Vector2() };
+	this.materialInitialSpectrum.uniforms.u_resolution = { value: this.resolution };
+	this.materialInitialSpectrum.depthTest = false;
+
+	// 4 - Phases used to animate heightmap
+	var phaseShader = THREE.ShaderLib[ "ocean_phase" ];
+	var phaseUniforms = THREE.UniformsUtils.clone( phaseShader.uniforms );
+	this.materialPhase = new THREE.ShaderMaterial( {
+		uniforms: phaseUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: phaseShader.fragmentShader
+	} );
+	this.materialPhase.uniforms.u_resolution = { value: this.resolution };
+	this.materialPhase.depthTest = false;
+
+	// 5 - Shader used to update spectrum
+	var spectrumShader = THREE.ShaderLib[ "ocean_spectrum" ];
+	var spectrumUniforms = THREE.UniformsUtils.clone( spectrumShader.uniforms );
+	this.materialSpectrum = new THREE.ShaderMaterial( {
+		uniforms: spectrumUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: spectrumShader.fragmentShader
+	} );
+	this.materialSpectrum.uniforms.u_initialSpectrum = { value: null };
+	this.materialSpectrum.uniforms.u_resolution = { value: this.resolution };
+	this.materialSpectrum.depthTest = false;
+
+	// 6 - Shader used to update spectrum normals
+	var normalShader = THREE.ShaderLib[ "ocean_normals" ];
+	var normalUniforms = THREE.UniformsUtils.clone( normalShader.uniforms );
+	this.materialNormal = new THREE.ShaderMaterial( {
+		uniforms: normalUniforms,
+		vertexShader: fullscreeenVertexShader.vertexShader,
+		fragmentShader: normalShader.fragmentShader
+	} );
+	this.materialNormal.uniforms.u_displacementMap = { value: null };
+	this.materialNormal.uniforms.u_resolution = { value: this.resolution };
+	this.materialNormal.depthTest = false;
+
+	// 7 - Shader used to update normals
+	var oceanShader = THREE.ShaderLib[ "ocean_main" ];
+	var oceanUniforms = THREE.UniformsUtils.clone( oceanShader.uniforms );
+	this.materialOcean = new THREE.ShaderMaterial( {
+		uniforms: oceanUniforms,
+		vertexShader: oceanShader.vertexShader,
+		fragmentShader: oceanShader.fragmentShader
+	} );
+	// this.materialOcean.wireframe = true;
+	this.materialOcean.uniforms.u_geometrySize = { value: this.resolution };
+	this.materialOcean.uniforms.u_displacementMap = { value: this.displacementMapFramebuffer.texture };
+	this.materialOcean.uniforms.u_normalMap = { value: this.normalMapFramebuffer.texture };
+	this.materialOcean.uniforms.u_oceanColor = { value: this.oceanColor };
+	this.materialOcean.uniforms.u_skyColor = { value: this.skyColor };
+	this.materialOcean.uniforms.u_sunDirection = { value: new THREE.Vector3( this.sunDirectionX, this.sunDirectionY, this.sunDirectionZ ) };
+	this.materialOcean.uniforms.u_exposure = { value: this.exposure };
+
+	// Disable blending to prevent default premultiplied alpha values
+	this.materialOceanHorizontal.blending = 0;
+	this.materialOceanVertical.blending = 0;
+	this.materialInitialSpectrum.blending = 0;
+	this.materialPhase.blending = 0;
+	this.materialSpectrum.blending = 0;
+	this.materialNormal.blending = 0;
+	this.materialOcean.blending = 0;
+
+	// Create the simulation plane
+	this.screenQuad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ) );
+	this.scene.add( this.screenQuad );
+
+	// Initialise spectrum data
+	this.generateSeedPhaseTexture();
+
+	// Generate the ocean mesh
+	this.generateMesh();
+
+};
+
+THREE.Ocean.prototype.generateMesh = function () {
+
+	var geometry = new THREE.PlaneBufferGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
+
+	geometry.rotateX( - Math.PI / 2 );
+
+	this.oceanMesh = new THREE.Mesh( geometry, this.materialOcean );
+
+};
+
+THREE.Ocean.prototype.render = function () {
+
+	this.scene.overrideMaterial = null;
+
+	if ( this.changed )
+		this.renderInitialSpectrum();
+
+	this.renderWavePhase();
+	this.renderSpectrum();
+	this.renderSpectrumFFT();
+	this.renderNormalMap();
+	this.scene.overrideMaterial = null;
+
+};
+
+THREE.Ocean.prototype.generateSeedPhaseTexture = function() {
+
+	// Setup the seed texture
+	this.pingPhase = true;
+	var phaseArray = new window.Float32Array( this.resolution * this.resolution * 4 );
+	for ( var i = 0; i < this.resolution; i ++ ) {
+
+		for ( var j = 0; j < this.resolution; j ++ ) {
+
+			phaseArray[ i * this.resolution * 4 + j * 4 ] =  Math.random() * 2.0 * Math.PI;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 1 ] = 0.0;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 2 ] = 0.0;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 3 ] = 0.0;
+
+		}
+
+	}
+
+	this.pingPhaseTexture = new THREE.DataTexture( phaseArray, this.resolution, this.resolution, THREE.RGBAFormat );
+	this.pingPhaseTexture.wrapS = THREE.ClampToEdgeWrapping;
+	this.pingPhaseTexture.wrapT = THREE.ClampToEdgeWrapping;
+	this.pingPhaseTexture.type = THREE.FloatType;
+	this.pingPhaseTexture.needsUpdate = true;
+
+};
+
+THREE.Ocean.prototype.renderInitialSpectrum = function () {
+
+	this.scene.overrideMaterial = this.materialInitialSpectrum;
+	this.materialInitialSpectrum.uniforms.u_wind.value.set( this.windX, this.windY );
+	this.materialInitialSpectrum.uniforms.u_size.value = this.size;
+	this.renderer.render( this.scene, this.oceanCamera, this.initialSpectrumFramebuffer, true );
+
+};
+
+THREE.Ocean.prototype.renderWavePhase = function () {
+
+	this.scene.overrideMaterial = this.materialPhase;
+	this.screenQuad.material = this.materialPhase;
+	if ( this.initial ) {
+
+		this.materialPhase.uniforms.u_phases.value = this.pingPhaseTexture;
+		this.initial = false;
+
+	}else {
+
+		this.materialPhase.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
+
+	}
+	this.materialPhase.uniforms.u_deltaTime.value = this.deltaTime;
+	this.materialPhase.uniforms.u_size.value = this.size;
+	this.renderer.render( this.scene, this.oceanCamera, this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer );
+	this.pingPhase = ! this.pingPhase;
+
+};
+
+THREE.Ocean.prototype.renderSpectrum = function () {
+
+	this.scene.overrideMaterial = this.materialSpectrum;
+	this.materialSpectrum.uniforms.u_initialSpectrum.value = this.initialSpectrumFramebuffer.texture;
+	this.materialSpectrum.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
+	this.materialSpectrum.uniforms.u_choppiness.value = this.choppiness;
+	this.materialSpectrum.uniforms.u_size.value = this.size;
+	this.renderer.render( this.scene, this.oceanCamera, this.spectrumFramebuffer );
+
+};
+
+THREE.Ocean.prototype.renderSpectrumFFT = function() {
+
+	// GPU FFT using Stockham formulation
+	var iterations = Math.log( this.resolution ) / Math.log( 2 ); // log2
+
+	this.scene.overrideMaterial = this.materialOceanHorizontal;
+
+	for ( var i = 0; i < iterations; i ++ ) {
+
+		if ( i === 0 ) {
+
+			this.materialOceanHorizontal.uniforms.u_input.value = this.spectrumFramebuffer.texture;
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+		} else if ( i % 2 === 1 ) {
+
+			this.materialOceanHorizontal.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+		} else {
+
+			this.materialOceanHorizontal.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+		}
+
+	}
+	this.scene.overrideMaterial = this.materialOceanVertical;
+	for ( var i = iterations; i < iterations * 2; i ++ ) {
+
+		if ( i === iterations * 2 - 1 ) {
+
+			this.materialOceanVertical.uniforms.u_input.value = ( iterations % 2 === 0 ) ? this.pingTransformFramebuffer.texture : this.pongTransformFramebuffer.texture;
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.displacementMapFramebuffer );
+
+		} else if ( i % 2 === 1 ) {
+
+			this.materialOceanVertical.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+		} else {
+
+			this.materialOceanVertical.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+		}
+
+	}
+
+};
+
+THREE.Ocean.prototype.renderNormalMap = function () {
+
+	this.scene.overrideMaterial = this.materialNormal;
+	if ( this.changed ) this.materialNormal.uniforms.u_size.value = this.size;
+	this.materialNormal.uniforms.u_displacementMap.value = this.displacementMapFramebuffer.texture;
+	this.renderer.render( this.scene, this.oceanCamera, this.normalMapFramebuffer, true );
+
+};

+ 2137 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Octree.js

@@ -0,0 +1,2137 @@
+/*!
+ *
+ * threeoctree.js (r60) / https://github.com/collinhover/threeoctree
+ * (sparse) dynamic 3D spatial representation structure for fast searches.
+ *
+ * @author Collin Hover / http://collinhover.com/
+ * based on Dynamic Octree by Piko3D @ http://www.piko3d.com/ and Octree by Marek Pawlowski @ pawlowski.it
+ *
+ */
+ ( function ( THREE ) {
+
+	"use strict";
+	
+	/*===================================================
+
+	utility
+
+	=====================================================*/
+	
+	function isNumber ( n ) {
+
+		return ! isNaN( n ) && isFinite( n );
+
+	}
+	
+	function isArray ( target ) {
+
+		return Object.prototype.toString.call( target ) === '[object Array]';
+
+	}
+	
+	function toArray ( target ) {
+
+		return target ? ( isArray ( target ) !== true ? [ target ] : target ) : [];
+
+	}
+	
+	function indexOfValue( array, value ) {
+		
+		for ( var i = 0, il = array.length; i < il; i ++ ) {
+			
+			if ( array[ i ] === value ) {
+				
+				return i;
+				
+			}
+			
+		}
+		
+		return - 1;
+		
+	}
+	
+	function indexOfPropertyWithValue( array, property, value ) {
+		
+		for ( var i = 0, il = array.length; i < il; i ++ ) {
+			
+			if ( array[ i ][ property ] === value ) {
+				
+				return i;
+				
+			}
+			
+		}
+		
+		return - 1;
+		
+	}
+
+	/*===================================================
+
+	octree
+
+	=====================================================*/
+
+	THREE.Octree = function ( parameters ) {
+		
+		// handle parameters
+		
+		parameters = parameters || {};
+		
+		parameters.tree = this;
+		
+		// static properties ( modification is not recommended )
+		
+		this.nodeCount = 0;
+		
+		this.INDEX_INSIDE_CROSS = - 1;
+		this.INDEX_OUTSIDE_OFFSET = 2;
+		
+		this.INDEX_OUTSIDE_POS_X = isNumber( parameters.INDEX_OUTSIDE_POS_X ) ? parameters.INDEX_OUTSIDE_POS_X : 0;
+		this.INDEX_OUTSIDE_NEG_X = isNumber( parameters.INDEX_OUTSIDE_NEG_X ) ? parameters.INDEX_OUTSIDE_NEG_X : 1;
+		this.INDEX_OUTSIDE_POS_Y = isNumber( parameters.INDEX_OUTSIDE_POS_Y ) ? parameters.INDEX_OUTSIDE_POS_Y : 2;
+		this.INDEX_OUTSIDE_NEG_Y = isNumber( parameters.INDEX_OUTSIDE_NEG_Y ) ? parameters.INDEX_OUTSIDE_NEG_Y : 3;
+		this.INDEX_OUTSIDE_POS_Z = isNumber( parameters.INDEX_OUTSIDE_POS_Z ) ? parameters.INDEX_OUTSIDE_POS_Z : 4;
+		this.INDEX_OUTSIDE_NEG_Z = isNumber( parameters.INDEX_OUTSIDE_NEG_Z ) ? parameters.INDEX_OUTSIDE_NEG_Z : 5;
+		
+		this.INDEX_OUTSIDE_MAP = [];
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_X ] = { index: this.INDEX_OUTSIDE_POS_X, count: 0, x: 1, y: 0, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_X ] = { index: this.INDEX_OUTSIDE_NEG_X, count: 0, x: - 1, y: 0, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Y ] = { index: this.INDEX_OUTSIDE_POS_Y, count: 0, x: 0, y: 1, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Y ] = { index: this.INDEX_OUTSIDE_NEG_Y, count: 0, x: 0, y: - 1, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Z ] = { index: this.INDEX_OUTSIDE_POS_Z, count: 0, x: 0, y: 0, z: 1 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Z ] = { index: this.INDEX_OUTSIDE_NEG_Z, count: 0, x: 0, y: 0, z: - 1 };
+		
+		this.FLAG_POS_X = 1 << ( this.INDEX_OUTSIDE_POS_X + 1 );
+		this.FLAG_NEG_X = 1 << ( this.INDEX_OUTSIDE_NEG_X + 1 );
+		this.FLAG_POS_Y = 1 << ( this.INDEX_OUTSIDE_POS_Y + 1 );
+		this.FLAG_NEG_Y = 1 << ( this.INDEX_OUTSIDE_NEG_Y + 1 );
+		this.FLAG_POS_Z = 1 << ( this.INDEX_OUTSIDE_POS_Z + 1 );
+		this.FLAG_NEG_Z = 1 << ( this.INDEX_OUTSIDE_NEG_Z + 1 );
+		
+		this.utilVec31Search = new THREE.Vector3();
+		this.utilVec32Search = new THREE.Vector3();
+		
+		// pass scene to see octree structure
+		
+		this.scene = parameters.scene;
+		
+		if ( this.scene ) {
+			
+			this.visualGeometry = new THREE.BoxGeometry( 1, 1, 1 );
+			this.visualMaterial = new THREE.MeshBasicMaterial( { color: 0xFF0066, wireframe: true, wireframeLinewidth: 1 } );
+			
+		}
+		
+		// properties
+		
+		this.objects = [];
+		this.objectsMap = {};
+		this.objectsData = [];
+		this.objectsDeferred = [];
+		
+		this.depthMax = isNumber( parameters.depthMax ) ? parameters.depthMax : Infinity;
+		this.objectsThreshold = isNumber( parameters.objectsThreshold ) ? parameters.objectsThreshold : 8;
+		this.overlapPct = isNumber( parameters.overlapPct ) ? parameters.overlapPct : 0.15;
+		this.undeferred = parameters.undeferred || false;
+		
+		this.root = parameters.root instanceof THREE.OctreeNode ? parameters.root : new THREE.OctreeNode( parameters );
+		
+	};
+
+	THREE.Octree.prototype = {
+		
+		update: function () {
+			
+			// add any deferred objects that were waiting for render cycle
+			
+			if ( this.objectsDeferred.length > 0 ) {
+				
+				for ( var i = 0, il = this.objectsDeferred.length; i < il; i ++ ) {
+					
+					var deferred = this.objectsDeferred[ i ];
+					
+					this.addDeferred( deferred.object, deferred.options );
+					
+				}
+				
+				this.objectsDeferred.length = 0;
+				
+			}
+			
+		},
+		
+		add: function ( object, options ) {
+			
+			// add immediately
+			
+			if ( this.undeferred ) {
+				
+				this.updateObject( object );
+				
+				this.addDeferred( object, options );
+				
+			} else {
+				
+				// defer add until update called
+				
+				this.objectsDeferred.push( { object: object, options: options } );
+				
+			}
+			
+		},
+		
+		addDeferred: function ( object, options ) {
+			
+			var i, l,
+				geometry,
+				faces,
+				useFaces,
+				vertices,
+				useVertices,
+				objectData;
+			
+			// ensure object is not object data
+			
+			if ( object instanceof THREE.OctreeObjectData ) {
+				
+				object = object.object;
+				
+			}
+			
+			// check uuid to avoid duplicates
+			
+			if ( ! object.uuid ) {
+				
+				object.uuid = THREE.Math.generateUUID();
+				
+			}
+			
+			if ( ! this.objectsMap[ object.uuid ] ) {
+				
+				// store
+				
+				this.objects.push( object );
+				this.objectsMap[ object.uuid ] = object;
+				
+				// check options
+				
+				if ( options ) {
+					
+					useFaces = options.useFaces;
+					useVertices = options.useVertices;
+					
+				}
+				
+				if ( useVertices === true ) {
+					
+					geometry = object.geometry;
+					vertices = geometry.vertices;
+					
+					for ( i = 0, l = vertices.length; i < l; i ++ ) {
+						
+						this.addObjectData( object, vertices[ i ] );
+						
+					}
+					
+				} else if ( useFaces === true ) {
+					
+					geometry = object.geometry;
+					faces = geometry.faces;
+					
+					for ( i = 0, l = faces.length; i < l; i ++ ) {
+						
+						this.addObjectData( object, faces[ i ] );
+						
+					}
+					
+				} else {
+					
+					this.addObjectData( object );
+					
+				}
+				
+			}
+			
+		},
+		
+		addObjectData: function ( object, part ) {
+			
+			var objectData = new THREE.OctreeObjectData( object, part );
+			
+			// add to tree objects data list
+			
+			this.objectsData.push( objectData );
+			
+			// add to nodes
+			
+			this.root.addObject( objectData );
+			
+		},
+		
+		remove: function ( object ) {
+			
+			var i, l,
+				objectData = object,
+				index,
+				objectsDataRemoved;
+			
+			// ensure object is not object data for index search
+			
+			if ( object instanceof THREE.OctreeObjectData ) {
+				
+				object = object.object;
+				
+			}
+			
+			// check uuid
+			
+			if ( this.objectsMap[ object.uuid ] ) {
+				
+				this.objectsMap[ object.uuid ] = undefined;
+				
+				// check and remove from objects, nodes, and data lists
+				
+				index = indexOfValue( this.objects, object );
+				
+				if ( index !== - 1 ) {
+					
+					this.objects.splice( index, 1 );
+					
+					// remove from nodes
+					
+					objectsDataRemoved = this.root.removeObject( objectData );
+					
+					// remove from objects data list
+					
+					for ( i = 0, l = objectsDataRemoved.length; i < l; i ++ ) {
+						
+						objectData = objectsDataRemoved[ i ];
+						
+						index = indexOfValue( this.objectsData, objectData );
+						
+						if ( index !== - 1 ) {
+							
+							this.objectsData.splice( index, 1 );
+							
+						}
+						
+					}
+					
+				}
+				
+			} else if ( this.objectsDeferred.length > 0 ) {
+				
+				// check and remove from deferred
+				
+				index = indexOfPropertyWithValue( this.objectsDeferred, 'object', object );
+				
+				if ( index !== - 1 ) {
+					
+					this.objectsDeferred.splice( index, 1 );
+					
+				}
+				
+			}
+			
+		},
+		
+		extend: function ( octree ) {
+			
+			var i, l,
+				objectsData,
+				objectData;
+				
+			if ( octree instanceof THREE.Octree ) {
+				
+				// for each object data
+				
+				objectsData = octree.objectsData;
+				
+				for ( i = 0, l = objectsData.length; i < l; i ++ ) {
+					
+					objectData = objectsData[ i ];
+					
+					this.add( objectData, { useFaces: objectData.faces, useVertices: objectData.vertices } );
+					
+				}
+				
+			}
+			
+		},
+		
+		rebuild: function () {
+			
+			var i, l,
+				node,
+				object,
+				objectData,
+				indexOctant,
+				indexOctantLast,
+				objectsUpdate = [];
+			
+			// check all object data for changes in position
+			// assumes all object matrices are up to date
+			
+			for ( i = 0, l = this.objectsData.length; i < l; i ++ ) {
+				
+				objectData = this.objectsData[ i ];
+				
+				node = objectData.node;
+				
+				// update object
+				
+				objectData.update();
+				
+				// if position has changed since last organization of object in tree
+				
+				if ( node instanceof THREE.OctreeNode && ! objectData.positionLast.equals( objectData.position ) ) {
+					
+					// get octant index of object within current node
+					
+					indexOctantLast = objectData.indexOctant;
+					
+					indexOctant = node.getOctantIndex( objectData );
+					
+					// if object octant index has changed
+					
+					if ( indexOctant !== indexOctantLast ) {
+						
+						// add to update list
+						
+						objectsUpdate.push( objectData );
+						
+					}
+					
+				}
+				
+			}
+			
+			// update changed objects
+			
+			for ( i = 0, l = objectsUpdate.length; i < l; i ++ ) {
+				
+				objectData = objectsUpdate[ i ];
+				
+				// remove object from current node
+				
+				objectData.node.removeObject( objectData );
+				
+				// add object to tree root
+				
+				this.root.addObject( objectData );
+				
+			}
+			
+		},
+		
+		updateObject: function ( object ) {
+			
+			var i, l,
+				parentCascade = [ object ],
+				parent,
+				parentUpdate;
+			
+			// search all parents between object and root for world matrix update
+			
+			parent = object.parent;
+			
+			while ( parent ) {
+				
+				parentCascade.push( parent );
+				parent = parent.parent;
+				
+			}
+			
+			for ( i = 0, l = parentCascade.length; i < l; i ++ ) {
+				
+				parent = parentCascade[ i ];
+				
+				if ( parent.matrixWorldNeedsUpdate === true ) {
+					
+					parentUpdate = parent;
+					
+				}
+				
+			}
+			
+			// update world matrix starting at uppermost parent that needs update
+			
+			if ( typeof parentUpdate !== 'undefined' ) {
+				
+				parentUpdate.updateMatrixWorld();
+				
+			}
+			
+		},
+		
+		search: function ( position, radius, organizeByObject, direction ) {
+			
+			var i, l,
+				node,
+				objects,
+				objectData,
+				object,
+				results,
+				resultData,
+				resultsObjectsIndices,
+				resultObjectIndex,
+				directionPct;
+			
+			// add root objects
+			
+			objects = [].concat( this.root.objects );
+			
+			// ensure radius (i.e. distance of ray) is a number
+			
+			if ( ! ( radius > 0 ) ) {
+				
+				radius = Number.MAX_VALUE;
+				
+			}
+			
+			// if direction passed, normalize and find pct
+			
+			if ( direction instanceof THREE.Vector3 ) {
+				
+				direction = this.utilVec31Search.copy( direction ).normalize();
+				directionPct = this.utilVec32Search.set( 1, 1, 1 ).divide( direction );
+				
+			}
+			
+			// search each node of root
+			
+			for ( i = 0, l = this.root.nodesIndices.length; i < l; i ++ ) {
+				
+				node = this.root.nodesByIndex[ this.root.nodesIndices[ i ] ];
+				
+				objects = node.search( position, radius, objects, direction, directionPct );
+				
+			}
+			
+			// if should organize results by object
+			
+			if ( organizeByObject === true ) {
+				
+				results = [];
+				resultsObjectsIndices = [];
+				
+				// for each object data found
+				
+				for ( i = 0, l = objects.length; i < l; i ++ ) {
+					
+					objectData = objects[ i ];
+					object = objectData.object;
+					
+					resultObjectIndex = indexOfValue( resultsObjectsIndices, object );
+					
+					// if needed, create new result data
+					
+					if ( resultObjectIndex === - 1 ) {
+						
+						resultData = {
+							object: object,
+							faces: [],
+							vertices: []
+						};
+						
+						results.push( resultData );
+						
+						resultsObjectsIndices.push( object );
+						
+					} else {
+						
+						resultData = results[ resultObjectIndex ];
+						
+					}
+					
+					// object data has faces or vertices, add to list
+					
+					if ( objectData.faces ) {
+						
+						resultData.faces.push( objectData.faces );
+						
+					} else if ( objectData.vertices ) {
+						
+						resultData.vertices.push( objectData.vertices );
+						
+					}
+					
+				}
+				
+			} else {
+				
+				results = objects;
+				
+			}
+			
+			return results;
+			
+		},
+		
+		setRoot: function ( root ) { 
+			
+			if ( root instanceof THREE.OctreeNode ) {
+				
+				// store new root
+				
+				this.root = root;
+				
+				// update properties
+				
+				this.root.updateProperties();
+				
+			}
+			
+		},
+		
+		getDepthEnd: function () {
+			
+			return this.root.getDepthEnd();
+			
+		},
+		
+		getNodeCountEnd: function () {
+			
+			return this.root.getNodeCountEnd();
+			
+		},
+		
+		getObjectCountEnd: function () {
+			
+			return this.root.getObjectCountEnd();
+			
+		},
+		
+		toConsole: function () {
+			
+			this.root.toConsole();
+			
+		}
+		
+	};
+
+	/*===================================================
+
+	object data
+
+	=====================================================*/
+
+	THREE.OctreeObjectData = function ( object, part ) {
+		
+		// properties
+		
+		this.object = object;
+		
+		// handle part by type
+		
+		if ( part instanceof THREE.Face3 ) {
+			
+			this.faces = part;
+			this.face3 = true;
+			this.utilVec31FaceBounds = new THREE.Vector3();
+			
+		} else if ( part instanceof THREE.Vector3 ) {
+			
+			this.vertices = part;
+			
+		}
+		
+		this.radius = 0;
+		this.position = new THREE.Vector3();
+			
+		// initial update
+		
+		if ( this.object instanceof THREE.Object3D ) {
+			
+			this.update();
+			
+		}
+		
+		this.positionLast = this.position.clone();
+		
+	};
+
+	THREE.OctreeObjectData.prototype = {
+		
+		update: function () {
+			
+			if ( this.face3 ) {
+				
+				this.radius = this.getFace3BoundingRadius( this.object, this.faces );
+				this.position.copy( this.faces.centroid ).applyMatrix4( this.object.matrixWorld );
+				
+			} else if ( this.vertices ) {
+				
+				this.radius = this.object.material.size || 1;
+				this.position.copy( this.vertices ).applyMatrix4( this.object.matrixWorld );
+				
+			} else {
+				
+				if ( this.object.geometry ) {
+					
+					if ( this.object.geometry.boundingSphere === null ) {
+						
+						this.object.geometry.computeBoundingSphere();
+						
+					}
+					
+					this.radius = this.object.geometry.boundingSphere.radius;
+					this.position.copy( this.object.geometry.boundingSphere.center ).applyMatrix4( this.object.matrixWorld );
+					
+				} else {
+					
+					this.radius = this.object.boundRadius;
+					this.position.setFromMatrixPosition( this.object.matrixWorld );
+					
+				}
+				
+			}
+			
+			this.radius = this.radius * Math.max( this.object.scale.x, this.object.scale.y, this.object.scale.z );
+			
+		},
+		
+		getFace3BoundingRadius: function ( object, face ) {
+
+			if ( face.centroid === undefined ) face.centroid = new THREE.Vector3();
+			
+			var geometry = object.geometry || object,
+				vertices = geometry.vertices,
+				centroid = face.centroid,
+				va = vertices[ face.a ], vb = vertices[ face.b ], vc = vertices[ face.c ],
+				centroidToVert = this.utilVec31FaceBounds,
+				radius;
+				
+			centroid.addVectors( va, vb ).add( vc ).divideScalar( 3 );
+			radius = Math.max( centroidToVert.subVectors( centroid, va ).length(), centroidToVert.subVectors( centroid, vb ).length(), centroidToVert.subVectors( centroid, vc ).length() );
+			
+			return radius;
+			
+		}
+		
+	};
+
+	/*===================================================
+
+	node
+
+	=====================================================*/
+
+	THREE.OctreeNode = function ( parameters ) {
+		
+		// utility
+		
+		this.utilVec31Branch = new THREE.Vector3();
+		this.utilVec31Expand = new THREE.Vector3();
+		this.utilVec31Ray = new THREE.Vector3();
+		
+		// handle parameters
+		
+		parameters = parameters || {};
+		
+		// store or create tree
+		
+		if ( parameters.tree instanceof THREE.Octree ) {
+			
+			this.tree = parameters.tree;
+			
+		} else if ( parameters.parent instanceof THREE.OctreeNode !== true ) {
+			
+			parameters.root = this;
+			
+			this.tree = new THREE.Octree( parameters );
+			
+		}
+		
+		// basic properties
+		
+		this.id = this.tree.nodeCount ++;
+		this.position = parameters.position instanceof THREE.Vector3 ? parameters.position : new THREE.Vector3();
+		this.radius = parameters.radius > 0 ? parameters.radius : 1;
+		this.indexOctant = parameters.indexOctant;
+		this.depth = 0;
+		
+		// reset and assign parent
+		
+		this.reset();
+		this.setParent( parameters.parent );
+		
+		// additional properties
+		
+		this.overlap = this.radius * this.tree.overlapPct;
+		this.radiusOverlap = this.radius + this.overlap;
+		this.left = this.position.x - this.radiusOverlap;
+		this.right = this.position.x + this.radiusOverlap;
+		this.bottom = this.position.y - this.radiusOverlap;
+		this.top = this.position.y + this.radiusOverlap;
+		this.back = this.position.z - this.radiusOverlap;
+		this.front = this.position.z + this.radiusOverlap;
+		
+		// visual
+		
+		if ( this.tree.scene ) {
+			
+			this.visual = new THREE.Mesh( this.tree.visualGeometry, this.tree.visualMaterial );
+			this.visual.scale.set( this.radiusOverlap * 2, this.radiusOverlap * 2, this.radiusOverlap * 2 );
+			this.visual.position.copy( this.position );
+			this.tree.scene.add( this.visual );
+			
+		}
+		
+	};
+
+	THREE.OctreeNode.prototype = {
+		
+		setParent: function ( parent ) {
+			
+			// store new parent
+			
+			if ( parent !== this && this.parent !== parent ) {
+				
+				this.parent = parent;
+				
+				// update properties
+				
+				this.updateProperties();
+				
+			}
+			
+		},
+		
+		updateProperties: function () {
+			
+			var i, l;
+			
+			// properties
+			
+			if ( this.parent instanceof THREE.OctreeNode ) {
+				
+				this.tree = this.parent.tree;
+				this.depth = this.parent.depth + 1;
+				
+			} else {
+				
+				this.depth = 0;
+				
+			}
+			
+			// cascade
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				this.nodesByIndex[ this.nodesIndices[ i ] ].updateProperties();
+				
+			}
+			
+		},
+		
+		reset: function ( cascade, removeVisual ) {
+			
+			var i, l,
+				node,
+				nodesIndices = this.nodesIndices || [],
+				nodesByIndex = this.nodesByIndex;
+			
+			this.objects = [];
+			this.nodesIndices = [];
+			this.nodesByIndex = {};
+			
+			// unset parent in nodes
+			
+			for ( i = 0, l = nodesIndices.length; i < l; i ++ ) {
+				
+				node = nodesByIndex[ nodesIndices[ i ] ];
+				
+				node.setParent( undefined );
+				
+				if ( cascade === true ) {
+					
+					node.reset( cascade, removeVisual );
+					
+				}
+				
+			}
+			
+			// visual
+			
+			if ( removeVisual === true && this.visual && this.visual.parent ) {
+				
+				this.visual.parent.remove( this.visual );
+				
+			}
+			
+		},
+		
+		addNode: function ( node, indexOctant ) {
+			
+			node.indexOctant = indexOctant;
+			
+			if ( indexOfValue( this.nodesIndices, indexOctant ) === - 1 ) {
+				
+				this.nodesIndices.push( indexOctant );
+				
+			}
+			
+			this.nodesByIndex[ indexOctant ] = node;
+			
+			if ( node.parent !== this ) {
+				
+				node.setParent( this );
+				
+			}
+			
+		},
+		
+		removeNode: function ( indexOctant ) {
+			
+			var index,
+				node;
+				
+			index = indexOfValue( this.nodesIndices, indexOctant );
+			
+			this.nodesIndices.splice( index, 1 );
+			
+			node = node || this.nodesByIndex[ indexOctant ];
+			
+			delete this.nodesByIndex[ indexOctant ];
+			
+			if ( node.parent === this ) {
+				
+				node.setParent( undefined );
+				
+			}
+			
+		},
+		
+		addObject: function ( object ) {
+			
+			var index,
+				indexOctant,
+				node;
+			
+			// get object octant index
+			
+			indexOctant = this.getOctantIndex( object );
+			
+			// if object fully contained by an octant, add to subtree
+			if ( indexOctant > - 1 && this.nodesIndices.length > 0 ) {
+				
+				node = this.branch( indexOctant );
+				
+				node.addObject( object );
+				
+			} else if ( indexOctant < - 1 && this.parent instanceof THREE.OctreeNode ) {
+				
+				// if object lies outside bounds, add to parent node
+				
+				this.parent.addObject( object );
+				
+			} else {
+				
+				// add to this objects list
+				
+				index = indexOfValue( this.objects, object );
+				
+				if ( index === - 1 ) {
+					
+					this.objects.push( object );
+					
+				}
+				
+				// node reference
+				
+				object.node = this;
+				
+				// check if need to expand, split, or both
+				
+				this.checkGrow();
+				
+			}
+			
+		},
+		
+		addObjectWithoutCheck: function ( objects ) {
+			
+			var i, l,
+				object;
+
+			for ( i = 0, l = objects.length; i < l; i ++ ) {
+				
+				object = objects[ i ];
+				
+				this.objects.push( object );
+				
+				object.node = this;
+				
+			}
+			
+		},
+		
+		removeObject: function ( object ) {
+			
+			var i, l,
+				nodesRemovedFrom,
+				removeData;
+			
+			// cascade through tree to find and remove object
+			
+			removeData = this.removeObjectRecursive( object, { searchComplete: false, nodesRemovedFrom: [], objectsDataRemoved: [] } );
+			
+			// if object removed, try to shrink the nodes it was removed from
+			
+			nodesRemovedFrom = removeData.nodesRemovedFrom;
+			
+			if ( nodesRemovedFrom.length > 0 ) {
+				
+				for ( i = 0, l = nodesRemovedFrom.length; i < l; i ++ ) {
+					
+					nodesRemovedFrom[ i ].shrink();
+					
+				}
+				
+			}
+			
+			return removeData.objectsDataRemoved;
+			
+		},
+		
+		removeObjectRecursive: function ( object, removeData ) {
+			
+			var i, l,
+				index = - 1,
+				objectData,
+				node,
+				objectRemoved;
+			
+			// find index of object in objects list
+			
+			// search and remove object data (fast)
+			if ( object instanceof THREE.OctreeObjectData ) {
+				
+				// remove from this objects list
+				
+				index = indexOfValue( this.objects, object );
+				
+				if ( index !== - 1 ) {
+					
+					this.objects.splice( index, 1 );
+					object.node = undefined;
+					
+					removeData.objectsDataRemoved.push( object );
+					
+					removeData.searchComplete = objectRemoved = true;
+					
+				}
+				
+			} else {
+			
+				// search each object data for object and remove (slow)
+				
+				for ( i = this.objects.length - 1; i >= 0; i -- ) {
+					
+					objectData = this.objects[ i ];
+					
+					if ( objectData.object === object ) {
+						
+						this.objects.splice( i, 1 );
+						objectData.node = undefined;
+						
+						removeData.objectsDataRemoved.push( objectData );
+						
+						objectRemoved = true;
+						
+						if ( ! objectData.faces && ! objectData.vertices ) {
+							
+							removeData.searchComplete = true;
+							break;
+							
+						}
+						
+					}
+					
+				}
+				
+			}
+			
+			// if object data removed and this is not on nodes removed from
+			
+			if ( objectRemoved === true ) {
+				
+				removeData.nodesRemovedFrom.push( this );
+				
+			}
+			
+			// if search not complete, search nodes
+			
+			if ( removeData.searchComplete !== true ) {
+				
+				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+					
+					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+					
+					// try removing object from node
+					
+					removeData = node.removeObjectRecursive( object, removeData );
+					
+					if ( removeData.searchComplete === true ) {
+						
+						break;
+						
+					}
+					
+				}
+				
+			}
+			
+			return removeData;
+			
+		},
+		
+		checkGrow: function () {
+			
+			// if object count above max
+			
+			if ( this.objects.length > this.tree.objectsThreshold && this.tree.objectsThreshold > 0 ) {
+				
+				this.grow();
+				
+			}
+			
+		},
+		
+		grow: function () {
+			
+			var indexOctant,
+				object,
+				objectsExpand = [],
+				objectsExpandOctants = [],
+				objectsSplit = [],
+				objectsSplitOctants = [],
+				objectsRemaining = [],
+				i, l;
+			
+			// for each object
+			
+			for ( i = 0, l = this.objects.length; i < l; i ++ ) {
+				
+				object = this.objects[ i ];
+				
+				// get object octant index
+				
+				indexOctant = this.getOctantIndex( object );
+				
+				// if lies within octant
+				if ( indexOctant > - 1 ) {
+					
+					objectsSplit.push( object );
+					objectsSplitOctants.push( indexOctant );
+				
+				} else if ( indexOctant < - 1 ) {
+					
+					// lies outside radius
+					
+					objectsExpand.push( object );
+					objectsExpandOctants.push( indexOctant );
+					
+				} else {
+				
+					// lies across bounds between octants
+					
+					objectsRemaining.push( object );
+					
+				}
+				
+			}
+			
+			// if has objects to split
+			
+			if ( objectsSplit.length > 0 ) {
+				
+				objectsRemaining = objectsRemaining.concat( this.split( objectsSplit, objectsSplitOctants ) );
+				
+			}
+			
+			// if has objects to expand
+			
+			if ( objectsExpand.length > 0 ) {
+				
+				objectsRemaining = objectsRemaining.concat( this.expand( objectsExpand, objectsExpandOctants ) );
+				
+			}
+			
+			// store remaining
+			
+			this.objects = objectsRemaining;
+			
+			// merge check
+			
+			this.checkMerge();
+			
+		},
+		
+		split: function ( objects, octants ) {
+			
+			var i, l,
+				indexOctant,
+				object,
+				node,
+				objectsRemaining;
+			
+			// if not at max depth
+			
+			if ( this.depth < this.tree.depthMax ) {
+				
+				objects = objects || this.objects;
+				
+				octants = octants || [];
+				
+				objectsRemaining = [];
+				
+				// for each object
+				
+				for ( i = 0, l = objects.length; i < l; i ++ ) {
+					
+					object = objects[ i ];
+					
+					// get object octant index
+					
+					indexOctant = octants[ i ];
+					
+					// if object contained by octant, branch this tree
+					
+					if ( indexOctant > - 1 ) {
+						
+						node = this.branch( indexOctant );
+						
+						node.addObject( object );
+						
+					} else {
+						
+						objectsRemaining.push( object );
+						
+					}
+					
+				}
+				
+				// if all objects, set remaining as new objects
+				
+				if ( objects === this.objects ) {
+					
+					this.objects = objectsRemaining;
+					
+				}
+				
+			} else {
+				
+				objectsRemaining = this.objects;
+				
+			}
+			
+			return objectsRemaining;
+			
+		},
+		
+		branch: function ( indexOctant ) {
+			
+			var node,
+				overlap,
+				radius,
+				radiusOffset,
+				offset,
+				position;
+			
+			// node exists
+			
+			if ( this.nodesByIndex[ indexOctant ] instanceof THREE.OctreeNode ) {
+				
+				node = this.nodesByIndex[ indexOctant ];
+				
+			} else {
+				
+				// properties
+				
+				radius = ( this.radiusOverlap ) * 0.5;
+				overlap = radius * this.tree.overlapPct;
+				radiusOffset = radius - overlap;
+				offset = this.utilVec31Branch.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
+				position = new THREE.Vector3().addVectors( this.position, offset );
+				
+				// node
+				
+				node = new THREE.OctreeNode( {
+					tree: this.tree,
+					parent: this,
+					position: position,
+					radius: radius,
+					indexOctant: indexOctant
+				} );
+				
+				// store
+				
+				this.addNode( node, indexOctant );
+			
+			}
+			
+			return node;
+			
+		},
+		
+		expand: function ( objects, octants ) {
+			
+			var i, l,
+				object,
+				objectsRemaining,
+				objectsExpand,
+				indexOctant,
+				flagsOutside,
+				indexOutside,
+				indexOctantInverse,
+				iom = this.tree.INDEX_OUTSIDE_MAP,
+				indexOutsideCounts,
+				infoIndexOutside1,
+				infoIndexOutside2,
+				infoIndexOutside3,
+				indexOutsideBitwise1,
+				indexOutsideBitwise2,
+				infoPotential1,
+				infoPotential2,
+				infoPotential3,
+				indexPotentialBitwise1,
+				indexPotentialBitwise2,
+				octantX, octantY, octantZ,
+				overlap,
+				radius,
+				radiusOffset,
+				radiusParent,
+				overlapParent,
+				offset = this.utilVec31Expand,
+				position,
+				parent;
+			
+			// handle max depth down tree
+			
+			if ( this.tree.root.getDepthEnd() < this.tree.depthMax ) {
+				
+				objects = objects || this.objects;
+				octants = octants || [];
+				
+				objectsRemaining = [];
+				objectsExpand = [];
+				
+				// reset counts
+				
+				for ( i = 0, l = iom.length; i < l; i ++ ) {
+					
+					iom[ i ].count = 0;
+					
+				}
+				
+				// for all outside objects, find outside octants containing most objects
+				
+				for ( i = 0, l = objects.length; i < l; i ++ ) {
+					
+					object = objects[ i ];
+					
+					// get object octant index
+					
+					indexOctant = octants[ i ] ;
+					
+					// if object outside this, include in calculations
+					
+					if ( indexOctant < - 1 ) {
+						
+						// convert octant index to outside flags
+						
+						flagsOutside = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
+						
+						// check against bitwise flags
+						
+						// x
+						
+						if ( flagsOutside & this.tree.FLAG_POS_X ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_POS_X ].count ++;
+							
+						} else if ( flagsOutside & this.tree.FLAG_NEG_X ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_NEG_X ].count ++;
+							
+						}
+						
+						// y
+						
+						if ( flagsOutside & this.tree.FLAG_POS_Y ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_POS_Y ].count ++;
+							
+						} else if ( flagsOutside & this.tree.FLAG_NEG_Y ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_NEG_Y ].count ++;
+							
+						}
+						
+						// z
+						
+						if ( flagsOutside & this.tree.FLAG_POS_Z ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_POS_Z ].count ++;
+							
+						} else if ( flagsOutside & this.tree.FLAG_NEG_Z ) {
+							
+							iom[ this.tree.INDEX_OUTSIDE_NEG_Z ].count ++;
+							
+						}
+						
+						// store in expand list
+						
+						objectsExpand.push( object );
+						
+					} else {
+						
+						objectsRemaining.push( object );
+						
+					}
+					
+				}
+				
+				// if objects to expand
+				
+				if ( objectsExpand.length > 0 ) {
+					
+					// shallow copy index outside map
+					
+					indexOutsideCounts = iom.slice( 0 );
+					
+					// sort outside index count so highest is first
+					
+					indexOutsideCounts.sort( function ( a, b ) {
+						
+						return b.count - a.count;
+						
+					} );
+					
+					// get highest outside indices
+					
+					// first is first
+					infoIndexOutside1 = indexOutsideCounts[ 0 ];
+					indexOutsideBitwise1 = infoIndexOutside1.index | 1;
+					
+					// second is ( one of next two bitwise OR 1 ) that is not opposite of ( first bitwise OR 1 )
+					
+					infoPotential1 = indexOutsideCounts[ 1 ];
+					infoPotential2 = indexOutsideCounts[ 2 ];
+					
+					infoIndexOutside2 = ( infoPotential1.index | 1 ) !== indexOutsideBitwise1 ? infoPotential1 : infoPotential2;
+					indexOutsideBitwise2 = infoIndexOutside2.index | 1;
+					
+					// third is ( one of next three bitwise OR 1 ) that is not opposite of ( first or second bitwise OR 1 )
+					
+					infoPotential1 = indexOutsideCounts[ 2 ];
+					infoPotential2 = indexOutsideCounts[ 3 ];
+					infoPotential3 = indexOutsideCounts[ 4 ];
+					
+					indexPotentialBitwise1 = infoPotential1.index | 1;
+					indexPotentialBitwise2 = infoPotential2.index | 1;
+					
+					infoIndexOutside3 = indexPotentialBitwise1 !== indexOutsideBitwise1 && indexPotentialBitwise1 !== indexOutsideBitwise2 ? infoPotential1 : indexPotentialBitwise2 !== indexOutsideBitwise1 && indexPotentialBitwise2 !== indexOutsideBitwise2 ? infoPotential2 : infoPotential3;
+					
+					// get this octant normal based on outside octant indices
+					
+					octantX = infoIndexOutside1.x + infoIndexOutside2.x + infoIndexOutside3.x;
+					octantY = infoIndexOutside1.y + infoIndexOutside2.y + infoIndexOutside3.y;
+					octantZ = infoIndexOutside1.z + infoIndexOutside2.z + infoIndexOutside3.z;
+					
+					// get this octant indices based on octant normal
+					
+					indexOctant = this.getOctantIndexFromPosition( octantX, octantY, octantZ );
+					indexOctantInverse = this.getOctantIndexFromPosition( - octantX, - octantY, - octantZ );
+					
+					// properties
+					
+					overlap = this.overlap;
+					radius = this.radius;
+					
+					// radius of parent comes from reversing overlap of this, unless overlap percent is 0
+					
+					radiusParent = this.tree.overlapPct > 0 ? overlap / ( ( 0.5 * this.tree.overlapPct ) * ( 1 + this.tree.overlapPct ) ) : radius * 2; 
+					overlapParent = radiusParent * this.tree.overlapPct;
+					
+					// parent offset is difference between radius + overlap of parent and child
+					
+					radiusOffset = ( radiusParent + overlapParent ) - ( radius + overlap );
+					offset.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
+					position = new THREE.Vector3().addVectors( this.position, offset );
+					
+					// parent
+					
+					parent = new THREE.OctreeNode( {
+						tree: this.tree,
+						position: position,
+						radius: radiusParent
+					} );
+					
+					// set self as node of parent
+					
+					parent.addNode( this, indexOctantInverse );
+					
+					// set parent as root
+					
+					this.tree.setRoot( parent );
+					
+					// add all expand objects to parent
+					
+					for ( i = 0, l = objectsExpand.length; i < l; i ++ ) {
+						
+						this.tree.root.addObject( objectsExpand[ i ] );
+						
+					}
+					
+				}
+				
+				// if all objects, set remaining as new objects
+				
+				if ( objects === this.objects ) {
+					
+					this.objects = objectsRemaining;
+					
+				}
+				
+			} else {
+				
+				objectsRemaining = objects;
+				
+			}
+			
+			return objectsRemaining;
+			
+		},
+		
+		shrink: function () {
+			
+			// merge check
+			
+			this.checkMerge();
+			
+			// contract check
+			
+			this.tree.root.checkContract();
+			
+		},
+		
+		checkMerge: function () {
+			
+			var nodeParent = this,
+				nodeMerge;
+			
+			// traverse up tree as long as node + entire subtree's object count is under minimum
+			
+			while ( nodeParent.parent instanceof THREE.OctreeNode && nodeParent.getObjectCountEnd() < this.tree.objectsThreshold ) {
+				
+				nodeMerge = nodeParent;
+				nodeParent = nodeParent.parent;
+				
+			}
+			
+			// if parent node is not this, merge entire subtree into merge node
+			
+			if ( nodeParent !== this ) {
+				
+				nodeParent.merge( nodeMerge );
+				
+			}
+			
+		},
+		
+		merge: function ( nodes ) {
+			
+			var i, l,
+				j, k,
+				node;
+			
+			// handle nodes
+			
+			nodes = toArray( nodes );
+			
+			for ( i = 0, l = nodes.length; i < l; i ++ ) {
+				
+				node = nodes[ i ];
+				
+				// gather node + all subtree objects
+				
+				this.addObjectWithoutCheck( node.getObjectsEnd() );
+				
+				// reset node + entire subtree
+				
+				node.reset( true, true );
+				
+				// remove node
+				
+				this.removeNode( node.indexOctant, node );
+				
+			}
+			
+			// merge check
+			
+			this.checkMerge();
+			
+		},
+		
+		checkContract: function () {
+			
+			var i, l,
+				node,
+				nodeObjectsCount,
+				nodeHeaviest,
+				nodeHeaviestObjectsCount,
+				outsideHeaviestObjectsCount;
+			
+			// find node with highest object count
+			
+			if ( this.nodesIndices.length > 0 ) {
+				
+				nodeHeaviestObjectsCount = 0;
+				outsideHeaviestObjectsCount = this.objects.length;
+				
+				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+					
+					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+					
+					nodeObjectsCount = node.getObjectCountEnd();
+					outsideHeaviestObjectsCount += nodeObjectsCount;
+					
+					if ( nodeHeaviest instanceof THREE.OctreeNode === false || nodeObjectsCount > nodeHeaviestObjectsCount ) {
+						
+						nodeHeaviest = node;
+						nodeHeaviestObjectsCount = nodeObjectsCount;
+						
+					}
+					
+				}
+				
+				// subtract heaviest count from outside count
+				
+				outsideHeaviestObjectsCount -= nodeHeaviestObjectsCount;
+				
+				// if should contract
+				
+				if ( outsideHeaviestObjectsCount < this.tree.objectsThreshold && nodeHeaviest instanceof THREE.OctreeNode ) {
+					
+					this.contract( nodeHeaviest );
+					
+				}
+				
+			}
+			
+		},
+		
+		contract: function ( nodeRoot ) {
+			
+			var i, l,
+				node;
+			
+			// handle all nodes
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+				
+				// if node is not new root
+				
+				if ( node !== nodeRoot ) {
+					
+					// add node + all subtree objects to root
+					
+					nodeRoot.addObjectWithoutCheck( node.getObjectsEnd() );
+					
+					// reset node + entire subtree
+					
+					node.reset( true, true );
+					
+				}
+				
+			}
+			
+			// add own objects to root
+			
+			nodeRoot.addObjectWithoutCheck( this.objects );
+			
+			// reset self
+			
+			this.reset( false, true );
+			
+			// set new root
+			
+			this.tree.setRoot( nodeRoot );
+			
+			// contract check on new root
+			
+			nodeRoot.checkContract();
+			
+		},
+		
+		getOctantIndex: function ( objectData ) {
+			
+			var i, l,
+				positionObj,
+				radiusObj,
+				position = this.position,
+				radiusOverlap = this.radiusOverlap,
+				overlap = this.overlap,
+				deltaX, deltaY, deltaZ,
+				distX, distY, distZ, 
+				distance,
+				indexOctant = 0;
+			
+			// handle type
+			
+			if ( objectData instanceof THREE.OctreeObjectData ) {
+				
+				radiusObj = objectData.radius;
+				
+				positionObj = objectData.position;
+				
+				// update object data position last
+				
+				objectData.positionLast.copy( positionObj );
+				
+			} else if ( objectData instanceof THREE.OctreeNode ) {
+				
+				positionObj = objectData.position;
+				
+				radiusObj = 0;
+				
+			}
+			
+			// find delta and distance
+			
+			deltaX = positionObj.x - position.x;
+			deltaY = positionObj.y - position.y;
+			deltaZ = positionObj.z - position.z;
+			
+			distX = Math.abs( deltaX );
+			distY = Math.abs( deltaY );
+			distZ = Math.abs( deltaZ );
+			distance = Math.max( distX, distY, distZ );
+			
+			// if outside, use bitwise flags to indicate on which sides object is outside of
+			
+			if ( distance + radiusObj > radiusOverlap ) {
+				
+				// x
+				
+				if ( distX + radiusObj > radiusOverlap ) {
+					
+					indexOctant = indexOctant ^ ( deltaX > 0 ? this.tree.FLAG_POS_X : this.tree.FLAG_NEG_X );
+					
+				}
+				
+				// y
+				
+				if ( distY + radiusObj > radiusOverlap ) {
+					
+					indexOctant = indexOctant ^ ( deltaY > 0 ? this.tree.FLAG_POS_Y : this.tree.FLAG_NEG_Y );
+					
+				}
+				
+				// z
+				
+				if ( distZ + radiusObj > radiusOverlap ) {
+					
+					indexOctant = indexOctant ^ ( deltaZ > 0 ? this.tree.FLAG_POS_Z : this.tree.FLAG_NEG_Z );
+					
+				}
+				
+				objectData.indexOctant = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
+				
+				return objectData.indexOctant;
+				
+			}
+			
+			// return octant index from delta xyz
+			
+			if ( deltaX - radiusObj > - overlap ) {
+				
+				// x right
+				
+				indexOctant = indexOctant | 1;
+				
+			} else if ( ! ( deltaX + radiusObj < overlap ) ) {
+				
+				// x left
+				
+				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
+				return objectData.indexOctant;
+				
+			}
+			
+			if ( deltaY - radiusObj > - overlap ) {
+				
+				// y right
+				
+				indexOctant = indexOctant | 2;
+				
+			} else if ( ! ( deltaY + radiusObj < overlap ) ) {
+				
+				// y left
+				
+				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
+				return objectData.indexOctant;
+				
+			}
+			
+			
+			if ( deltaZ - radiusObj > - overlap ) {
+				
+				// z right
+				
+				indexOctant = indexOctant | 4;
+				
+			} else if ( ! ( deltaZ + radiusObj < overlap ) ) {
+				
+				// z left
+				
+				objectData.indexOctant = this.tree.INDEX_INSIDE_CROSS;
+				return objectData.indexOctant;
+				
+			}
+			
+			objectData.indexOctant = indexOctant;
+			return objectData.indexOctant;
+			
+		},
+		
+		getOctantIndexFromPosition: function ( x, y, z ) {
+			
+			var indexOctant = 0;
+			
+			if ( x > 0 ) {
+				
+				indexOctant = indexOctant | 1;
+				
+			}
+			
+			if ( y > 0 ) {
+				
+				indexOctant = indexOctant | 2;
+				
+			}
+			
+			if ( z > 0 ) {
+				
+				indexOctant = indexOctant | 4;
+				
+			}
+			
+			return indexOctant;
+			
+		},
+		
+		search: function ( position, radius, objects, direction, directionPct ) {
+			
+			var i, l,
+				node,
+				intersects;
+			
+			// test intersects by parameters
+			
+			if ( direction ) {
+				
+				intersects = this.intersectRay( position, direction, radius, directionPct );
+				
+			} else {
+				
+				intersects = this.intersectSphere( position, radius );
+				
+			}
+			
+			// if intersects
+			
+			if ( intersects === true ) {
+				
+				// gather objects
+				
+				objects = objects.concat( this.objects );
+				
+				// search subtree
+				
+				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+					
+					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+					
+					objects = node.search( position, radius, objects, direction );
+					
+				}
+				
+			}
+			
+			return objects;
+			
+		},
+		
+		intersectSphere: function ( position, radius ) {
+			
+			var	distance = radius * radius,
+				px = position.x,
+				py = position.y,
+				pz = position.z;
+			
+			if ( px < this.left ) {
+
+				distance -= Math.pow( px - this.left, 2 );
+
+			} else if ( px > this.right ) {
+
+				distance -= Math.pow( px - this.right, 2 );
+
+			}
+			
+			if ( py < this.bottom ) {
+
+				distance -= Math.pow( py - this.bottom, 2 );
+
+			} else if ( py > this.top ) {
+
+				distance -= Math.pow( py - this.top, 2 );
+
+			}
+			
+			if ( pz < this.back ) {
+
+				distance -= Math.pow( pz - this.back, 2 );
+
+			} else if ( pz > this.front ) {
+
+				distance -= Math.pow( pz - this.front, 2 );
+
+			}
+			
+			return distance >= 0;
+			
+		},
+		
+		intersectRay: function ( origin, direction, distance, directionPct ) {
+			
+			if ( typeof directionPct === 'undefined' ) {
+				
+				directionPct = this.utilVec31Ray.set( 1, 1, 1 ).divide( direction );
+				
+			}
+			
+			var t1 = ( this.left - origin.x ) * directionPct.x,
+				t2 = ( this.right - origin.x ) * directionPct.x,
+				t3 = ( this.bottom - origin.y ) * directionPct.y,
+				t4 = ( this.top - origin.y ) * directionPct.y,
+				t5 = ( this.back - origin.z ) * directionPct.z,
+				t6 = ( this.front - origin.z ) * directionPct.z,
+				tmax = Math.min( Math.min( Math.max( t1, t2 ), Math.max( t3, t4 ) ), Math.max( t5, t6 ) ),
+				tmin;
+
+			// ray would intersect in reverse direction, i.e. this is behind ray
+			if ( tmax < 0 ) {
+
+				return false;
+
+			}
+			
+			tmin = Math.max( Math.max( Math.min( t1, t2 ), Math.min( t3, t4 ) ), Math.min( t5, t6 ) );
+			
+			// if tmin > tmax or tmin > ray distance, ray doesn't intersect AABB
+			if ( tmin > tmax || tmin > distance ) {
+
+				return false;
+
+			}
+			
+			return true;
+			
+		},
+		
+		getDepthEnd: function ( depth ) {
+			
+			var i, l,
+				node;
+
+			if ( this.nodesIndices.length > 0 ) {
+				
+				for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+
+					node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+
+					depth = node.getDepthEnd( depth );
+
+				}
+				
+			} else {
+
+				depth = ! depth || this.depth > depth ? this.depth : depth;
+
+			}
+
+			return depth;
+			
+		},
+		
+		getNodeCountEnd: function () {
+			
+			return this.tree.root.getNodeCountRecursive() + 1;
+			
+		},
+		
+		getNodeCountRecursive: function () {
+			
+			var i, l,
+				count = this.nodesIndices.length;
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				count += this.nodesByIndex[ this.nodesIndices[ i ] ].getNodeCountRecursive();
+				
+			}
+			
+			return count;
+			
+		},
+		
+		getObjectsEnd: function ( objects ) {
+			
+			var i, l,
+				node;
+			
+			objects = ( objects || [] ).concat( this.objects );
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+				
+				objects = node.getObjectsEnd( objects );
+				
+			}
+			
+			return objects;
+			
+		},
+		
+		getObjectCountEnd: function () {
+			
+			var i, l,
+				count = this.objects.length;
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				count += this.nodesByIndex[ this.nodesIndices[ i ] ].getObjectCountEnd();
+				
+			}
+			
+			return count;
+			
+		},
+		
+		getObjectCountStart: function () {
+			
+			var count = this.objects.length,
+				parent = this.parent;
+			
+			while ( parent instanceof THREE.OctreeNode ) {
+				
+				count += parent.objects.length;
+				parent = parent.parent;
+				
+			}
+			
+			return count;
+			
+		},
+		
+		toConsole: function ( space ) {
+			
+			var i, l,
+				node,
+				spaceAddition = '   ';
+			
+			space = typeof space === 'string' ? space : spaceAddition;
+			
+			console.log( ( this.parent ? space + ' octree NODE > ' : ' octree ROOT > ' ), this, ' // id: ', this.id, ' // indexOctant: ', this.indexOctant, ' // position: ', this.position.x, this.position.y, this.position.z, ' // radius: ', this.radius, ' // depth: ', this.depth );
+			console.log( ( this.parent ? space + ' ' : ' ' ), '+ objects ( ', this.objects.length, ' ) ', this.objects );
+			console.log( ( this.parent ? space + ' ' : ' ' ), '+ children ( ', this.nodesIndices.length, ' )', this.nodesIndices, this.nodesByIndex );
+			
+			for ( i = 0, l = this.nodesIndices.length; i < l; i ++ ) {
+				
+				node = this.nodesByIndex[ this.nodesIndices[ i ] ];
+				
+				node.toConsole( space + spaceAddition );
+				
+			}
+			
+		}
+		
+	};
+
+	/*===================================================
+
+	raycaster additional functionality
+
+	=====================================================*/
+	
+	THREE.Raycaster.prototype.intersectOctreeObject = function ( object, recursive ) {
+		
+		var intersects,
+			octreeObject,
+			facesAll,
+			facesSearch;
+		
+		if ( object.object instanceof THREE.Object3D ) {
+			
+			octreeObject = object;
+			object = octreeObject.object;
+			
+			// temporarily replace object geometry's faces with octree object faces
+			
+			facesSearch = octreeObject.faces;
+			facesAll = object.geometry.faces;
+			
+			if ( facesSearch.length > 0 ) {
+				
+				object.geometry.faces = facesSearch;
+				
+			}
+			
+			// intersect
+			
+			intersects = this.intersectObject( object, recursive );
+			
+			// revert object geometry's faces
+			
+			if ( facesSearch.length > 0 ) {
+				
+				object.geometry.faces = facesAll;
+				
+			}
+			
+		} else {
+			
+			intersects = this.intersectObject( object, recursive );
+			
+		}
+		
+		return intersects;
+		
+	};
+	
+	THREE.Raycaster.prototype.intersectOctreeObjects = function ( objects, recursive ) {
+		
+		var i, il,
+			intersects = [];
+		
+		for ( i = 0, il = objects.length; i < il; i ++ ) {
+			
+			intersects = intersects.concat( this.intersectOctreeObject( objects[ i ], recursive ) );
+		
+		}
+		
+		return intersects;
+		
+	};
+
+}( THREE ) );

+ 23 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/PRNG.js

@@ -0,0 +1,23 @@
+// Park-Miller-Carta Pseudo-Random Number Generator
+// https://github.com/pnitsch/BitmapData.js/blob/master/js/BitmapData.js
+
+var PRNG = function () {
+
+	this.seed = 1;
+	this.next = function() {
+
+		return ( this.gen() / 2147483647 );
+
+	};
+	this.nextRange = function( min, max )	{
+
+		return min + ( ( max - min ) * this.next() )
+
+	};
+	this.gen = function() {
+
+		return this.seed = ( this.seed * 16807 ) % 2147483647;
+
+	};
+
+};

+ 269 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ParametricGeometries.js

@@ -0,0 +1,269 @@
+/*
+ * @author zz85
+ *
+ * Experimenting of primitive geometry creation using Surface Parametric equations
+ *
+ */
+
+
+THREE.ParametricGeometries = {
+
+	klein: function ( v, u ) {
+
+		u *= Math.PI;
+		v *= 2 * Math.PI;
+
+		u = u * 2;
+		var x, y, z;
+		if ( u < Math.PI ) {
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( u ) * Math.cos( v );
+			z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v );
+
+		} else {
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( v + Math.PI );
+			z = - 8 * Math.sin( u );
+
+		}
+
+		y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v );
+
+		return new THREE.Vector3( x, y, z );
+
+	},
+
+	plane: function ( width, height ) {
+
+		return function( u, v ) {
+
+			var x = u * width;
+			var y = 0;
+			var z = v * height;
+
+			return new THREE.Vector3( x, y, z );
+
+		};
+
+	},
+
+	mobius: function( u, t ) {
+
+		// flat mobius strip
+		// http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
+		u = u - 0.5;
+		var v = 2 * Math.PI * t;
+
+		var x, y, z;
+
+		var a = 2;
+		x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) );
+		y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) );
+		z = u * Math.sin( v / 2 );
+		return new THREE.Vector3( x, y, z );
+
+	},
+
+	mobius3d: function( u, t ) {
+
+		// volumetric mobius strip
+		u *= Math.PI;
+		t *= 2 * Math.PI;
+
+		u = u * 2;
+		var phi = u / 2;
+		var major = 2.25, a = 0.125, b = 0.65;
+		var x, y, z;
+		x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi );
+		z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi );
+		y = ( major + x ) * Math.sin( u );
+		x = ( major + x ) * Math.cos( u );
+		return new THREE.Vector3( x, y, z );
+
+	}
+
+};
+
+
+/*********************************************
+ *
+ * Parametric Replacement for TubeGeometry
+ *
+ *********************************************/
+
+THREE.ParametricGeometries.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, debug ) {
+
+	this.path = path;
+	this.segments = segments || 64;
+	this.radius = radius || 1;
+	this.segmentsRadius = segmentsRadius || 8;
+	this.closed = closed || false;
+	if ( debug ) this.debug = new THREE.Object3D();
+
+
+	var scope = this,
+
+		tangent, normal, binormal,
+
+		numpoints = this.segments + 1,
+
+		x, y, z, tx, ty, tz, u, v,
+
+		cx, cy, pos, pos2 = new THREE.Vector3(),
+		i, j, ip, jp, a, b, c, d, uva, uvb, uvc, uvd;
+
+	var frames = path.computeFrenetFrames( segments, closed ),
+		tangents = frames.tangents,
+		normals = frames.normals,
+		binormals = frames.binormals;
+
+	// proxy internals
+	this.tangents = tangents;
+	this.normals = normals;
+	this.binormals = binormals;
+
+
+
+	var ParametricTube = function( u, v ) {
+
+		v *= 2 * Math.PI;
+
+		i = u * ( numpoints - 1 );
+		i = Math.floor( i );
+
+		pos = path.getPointAt( u );
+
+		tangent = tangents[ i ];
+		normal = normals[ i ];
+		binormal = binormals[ i ];
+
+		if ( scope.debug ) {
+
+			scope.debug.add( new THREE.ArrowHelper( tangent, pos, radius, 0x0000ff ) );
+			scope.debug.add( new THREE.ArrowHelper( normal, pos, radius, 0xff0000 ) );
+			scope.debug.add( new THREE.ArrowHelper( binormal, pos, radius, 0x00ff00 ) );
+
+		}
+
+		cx = - scope.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
+		cy = scope.radius * Math.sin( v );
+
+		pos2.copy( pos );
+		pos2.x += cx * normal.x + cy * binormal.x;
+		pos2.y += cx * normal.y + cy * binormal.y;
+		pos2.z += cx * normal.z + cy * binormal.z;
+
+		return pos2.clone();
+
+	};
+
+	THREE.ParametricGeometry.call( this, ParametricTube, segments, segmentsRadius );
+
+};
+
+THREE.ParametricGeometries.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
+THREE.ParametricGeometries.TubeGeometry.prototype.constructor = THREE.ParametricGeometries.TubeGeometry;
+
+
+ /*********************************************
+  *
+  * Parametric Replacement for TorusKnotGeometry
+  *
+  *********************************************/
+THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsT, segmentsR, p, q ) {
+
+	var scope = this;
+
+	this.radius = radius || 200;
+	this.tube = tube || 40;
+	this.segmentsT = segmentsT || 64;
+	this.segmentsR = segmentsR || 8;
+	this.p = p || 2;
+	this.q = q || 3;
+
+	var TorusKnotCurve = THREE.Curve.create(
+
+		function() {
+		},
+
+		function( t ) {
+
+			t *= Math.PI * 2;
+
+			var r = 0.5;
+
+			var tx = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t ),
+				ty = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t ),
+				tz = r * Math.sin( q * t );
+
+			return new THREE.Vector3( tx, ty, tz ).multiplyScalar( radius );
+
+		}
+
+	);
+	var segments = segmentsT;
+	var radiusSegments = segmentsR;
+	var extrudePath = new TorusKnotCurve();
+
+	THREE.ParametricGeometries.TubeGeometry.call( this, extrudePath, segments, tube, radiusSegments, true, false );
+
+
+};
+
+THREE.ParametricGeometries.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
+THREE.ParametricGeometries.TorusKnotGeometry.prototype.constructor = THREE.ParametricGeometries.TorusKnotGeometry;
+
+
+ /*********************************************
+  *
+  * Parametric Replacement for SphereGeometry
+  *
+  *********************************************/
+THREE.ParametricGeometries.SphereGeometry = function( size, u, v ) {
+
+	function sphere( u, v ) {
+
+		u *= Math.PI;
+		v *= 2 * Math.PI;
+
+		var x = size * Math.sin( u ) * Math.cos( v );
+		var y = size * Math.sin( u ) * Math.sin( v );
+		var z = size * Math.cos( u );
+
+
+		return new THREE.Vector3( x, y, z );
+
+	}
+
+	THREE.ParametricGeometry.call( this, sphere, u, v, ! true );
+
+};
+
+THREE.ParametricGeometries.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
+THREE.ParametricGeometries.SphereGeometry.prototype.constructor = THREE.ParametricGeometries.SphereGeometry;
+
+
+ /*********************************************
+  *
+  * Parametric Replacement for PlaneGeometry
+  *
+  *********************************************/
+
+THREE.ParametricGeometries.PlaneGeometry = function( width, depth, segmentsWidth, segmentsDepth ) {
+
+	function plane( u, v ) {
+
+		var x = u * width;
+		var y = 0;
+		var z = v * depth;
+
+		return new THREE.Vector3( x, y, z );
+
+	}
+
+	THREE.ParametricGeometry.call( this, plane, segmentsWidth, segmentsDepth );
+
+};
+
+THREE.ParametricGeometries.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
+THREE.ParametricGeometries.PlaneGeometry.prototype.constructor = THREE.ParametricGeometries.PlaneGeometry;

+ 544 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/RollerCoaster.js

@@ -0,0 +1,544 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var RollerCoasterGeometry = function ( curve, size ) {
+
+	THREE.BufferGeometry.call( this );
+
+	var vertices = [];
+	var normals = [];
+	var colors = [];
+
+	var color1 = [ 1, 1, 1 ];
+	var color2 = [ 1, 1, 0 ];
+
+	var up = new THREE.Vector3( 0, 1, 0 );
+	var forward = new THREE.Vector3();
+	var right = new THREE.Vector3();
+
+	var quaternion = new THREE.Quaternion();
+	var prevQuaternion = new THREE.Quaternion();
+	prevQuaternion.setFromAxisAngle( up , Math.PI / 2 );
+
+	var point = new THREE.Vector3();
+	var prevPoint = new THREE.Vector3();
+	prevPoint.copy( curve.getPointAt( 0 ) );
+
+	// shapes
+
+	var step = [
+		new THREE.Vector3( -2.25,  0, 0 ),
+		new THREE.Vector3(  0,  -0.5, 0 ),
+		new THREE.Vector3(  0, -1.75, 0 ),
+
+		new THREE.Vector3(  0,  -0.5, 0 ),
+		new THREE.Vector3(  2.25,  0, 0 ),
+		new THREE.Vector3(  0, -1.75, 0 )
+	];
+
+	var PI2 = Math.PI * 2;
+
+	var sides = 5;
+	var tube1 = [];
+
+	for ( var i = 0; i < sides; i ++ ) {
+
+		var angle = ( i / sides ) * PI2;
+		tube1.push( new THREE.Vector3( Math.sin( angle ) * 0.6, Math.cos( angle ) * 0.6, 0 ) );
+
+	}
+
+	var sides = 6;
+	var tube2 = [];
+
+	for ( var i = 0; i < sides; i ++ ) {
+
+		var angle = ( i / sides ) * PI2;
+		tube2.push( new THREE.Vector3( Math.sin( angle ) * 0.25, Math.cos( angle ) * 0.25, 0 ) );
+
+	}
+
+	var vector = new THREE.Vector3();
+	var normal = new THREE.Vector3();
+
+	var drawShape = function ( shape, color ) {
+
+		normal.set( 0, 0, -1 ).applyQuaternion( quaternion );
+
+		for ( var j = 0; j < shape.length; j ++ ) {
+
+			vector.copy( shape[ j ] );
+			vector.applyQuaternion( quaternion );
+			vector.add( point );
+
+			vertices.push( vector.x, vector.y, vector.z );
+			normals.push( normal.x, normal.y, normal.z );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+
+		}
+
+		normal.set( 0, 0, 1 ).applyQuaternion( quaternion );
+
+		for ( var j = shape.length - 1; j >= 0; j -- ) {
+
+			vector.copy( shape[ j ] );
+			vector.applyQuaternion( quaternion );
+			vector.add( point );
+
+			vertices.push( vector.x, vector.y, vector.z );
+			normals.push( normal.x, normal.y, normal.z );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+
+		}
+
+	};
+
+	var vector1 = new THREE.Vector3();
+	var vector2 = new THREE.Vector3();
+	var vector3 = new THREE.Vector3();
+	var vector4 = new THREE.Vector3();
+
+	var normal1 = new THREE.Vector3();
+	var normal2 = new THREE.Vector3();
+	var normal3 = new THREE.Vector3();
+	var normal4 = new THREE.Vector3();
+
+	var extrudeShape = function ( shape, offset, color ) {
+
+		for ( var j = 0, jl = shape.length; j < jl; j ++ ) {
+
+			var point1 = shape[ j ];
+			var point2 = shape[ ( j + 1 ) % jl ];
+
+			vector1.copy( point1 ).add( offset );
+			vector1.applyQuaternion( quaternion );
+			vector1.add( point );
+
+			vector2.copy( point2 ).add( offset );
+			vector2.applyQuaternion( quaternion );
+			vector2.add( point );
+
+			vector3.copy( point2 ).add( offset );
+			vector3.applyQuaternion( prevQuaternion );
+			vector3.add( prevPoint );
+
+			vector4.copy( point1 ).add( offset );
+			vector4.applyQuaternion( prevQuaternion );
+			vector4.add( prevPoint );
+
+			vertices.push( vector1.x, vector1.y, vector1.z );
+			vertices.push( vector2.x, vector2.y, vector2.z );
+			vertices.push( vector4.x, vector4.y, vector4.z );
+
+			vertices.push( vector2.x, vector2.y, vector2.z );
+			vertices.push( vector3.x, vector3.y, vector3.z );
+			vertices.push( vector4.x, vector4.y, vector4.z );
+
+			//
+
+			normal1.copy( point1 );
+			normal1.applyQuaternion( quaternion );
+			normal1.normalize();
+
+			normal2.copy( point2 );
+			normal2.applyQuaternion( quaternion );
+			normal2.normalize();
+
+			normal3.copy( point2 );
+			normal3.applyQuaternion( prevQuaternion );
+			normal3.normalize();
+
+			normal4.copy( point1 );
+			normal4.applyQuaternion( prevQuaternion );
+			normal4.normalize();
+
+			normals.push( normal1.x, normal1.y, normal1.z );
+			normals.push( normal2.x, normal2.y, normal2.z );
+			normals.push( normal4.x, normal4.y, normal4.z );
+
+			normals.push( normal2.x, normal2.y, normal2.z );
+			normals.push( normal3.x, normal3.y, normal3.z );
+			normals.push( normal4.x, normal4.y, normal4.z );
+
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+			colors.push( color[ 0 ], color[ 1 ], color[ 2 ] );
+
+		}
+
+	};
+
+	var offset = new THREE.Vector3();
+
+	for ( var i = 1; i <= size; i ++ ) {
+
+		point.copy( curve.getPointAt( i / size ) );
+
+		up.set( 0, 1, 0 );
+
+		forward.subVectors( point, prevPoint ).normalize();
+		right.crossVectors( up, forward ).normalize();
+		up.crossVectors( forward, right );
+
+		var angle = Math.atan2( forward.x, forward.z );
+
+		quaternion.setFromAxisAngle( up, angle );
+
+		if ( i % 2 === 0 ) {
+
+			drawShape( step, color2 );
+
+		}
+
+		extrudeShape( tube1, offset.set( 0, -1.25, 0 ), color2 );
+		extrudeShape( tube2, offset.set( 2, 0, 0 ), color1 );
+		extrudeShape( tube2, offset.set( -2, 0, 0 ), color1 );
+
+		prevPoint.copy( point );
+		prevQuaternion.copy( quaternion );
+
+	}
+
+	// console.log( vertices.length );
+
+	this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+	this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
+	this.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
+
+};
+
+RollerCoasterGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+
+var RollerCoasterLiftersGeometry = function ( curve, size ) {
+
+	THREE.BufferGeometry.call( this );
+
+	var vertices = [];
+	var normals = [];
+
+	var quaternion = new THREE.Quaternion();
+
+	var up = new THREE.Vector3( 0, 1, 0 );
+
+	var point = new THREE.Vector3();
+	var tangent = new THREE.Vector3();
+
+	// shapes
+
+	var tube1 = [
+		new THREE.Vector3(  0,  0.5, -0.5 ),
+		new THREE.Vector3(  0,  0.5,  0.5 ),
+		new THREE.Vector3(  0, -0.5,  0 )
+	];
+
+	var tube2 = [
+		new THREE.Vector3( -0.5, 0,  0.5 ),
+		new THREE.Vector3( -0.5, 0, -0.5 ),
+		new THREE.Vector3(  0.5, 0,  0 )
+	];
+
+	var tube3 = [
+		new THREE.Vector3(  0.5, 0, -0.5 ),
+		new THREE.Vector3(  0.5, 0,  0.5 ),
+		new THREE.Vector3( -0.5, 0,  0 )
+	];
+
+	var vector1 = new THREE.Vector3();
+	var vector2 = new THREE.Vector3();
+	var vector3 = new THREE.Vector3();
+	var vector4 = new THREE.Vector3();
+
+	var normal1 = new THREE.Vector3();
+	var normal2 = new THREE.Vector3();
+	var normal3 = new THREE.Vector3();
+	var normal4 = new THREE.Vector3();
+
+	var extrudeShape = function ( shape, fromPoint, toPoint ) {
+
+		for ( var j = 0, jl = shape.length; j < jl; j ++ ) {
+
+			var point1 = shape[ j ];
+			var point2 = shape[ ( j + 1 ) % jl ];
+
+			vector1.copy( point1 );
+			vector1.applyQuaternion( quaternion );
+			vector1.add( fromPoint );
+
+			vector2.copy( point2 );
+			vector2.applyQuaternion( quaternion );
+			vector2.add( fromPoint );
+
+			vector3.copy( point2 );
+			vector3.applyQuaternion( quaternion );
+			vector3.add( toPoint );
+
+			vector4.copy( point1 );
+			vector4.applyQuaternion( quaternion );
+			vector4.add( toPoint );
+
+			vertices.push( vector1.x, vector1.y, vector1.z );
+			vertices.push( vector2.x, vector2.y, vector2.z );
+			vertices.push( vector4.x, vector4.y, vector4.z );
+
+			vertices.push( vector2.x, vector2.y, vector2.z );
+			vertices.push( vector3.x, vector3.y, vector3.z );
+			vertices.push( vector4.x, vector4.y, vector4.z );
+
+			//
+
+			normal1.copy( point1 );
+			normal1.applyQuaternion( quaternion );
+			normal1.normalize();
+
+			normal2.copy( point2 );
+			normal2.applyQuaternion( quaternion );
+			normal2.normalize();
+
+			normal3.copy( point2 );
+			normal3.applyQuaternion( quaternion );
+			normal3.normalize();
+
+			normal4.copy( point1 );
+			normal4.applyQuaternion( quaternion );
+			normal4.normalize();
+
+			normals.push( normal1.x, normal1.y, normal1.z );
+			normals.push( normal2.x, normal2.y, normal2.z );
+			normals.push( normal4.x, normal4.y, normal4.z );
+
+			normals.push( normal2.x, normal2.y, normal2.z );
+			normals.push( normal3.x, normal3.y, normal3.z );
+			normals.push( normal4.x, normal4.y, normal4.z );
+
+		}
+
+	};
+
+	var fromPoint = new THREE.Vector3();
+	var toPoint = new THREE.Vector3();
+
+	for ( var i = 1; i <= size; i ++ ) {
+
+		point.copy( curve.getPointAt( i / size ) );
+		tangent.copy( curve.getTangentAt( i / size ) );
+
+		var angle = Math.atan2( tangent.x, tangent.z );
+
+		quaternion.setFromAxisAngle( up, angle );
+
+		//
+
+		if ( point.y > 100 ) {
+
+			fromPoint.set( -7.5, -3.5, 0 );
+			fromPoint.applyQuaternion( quaternion );
+			fromPoint.add( point );
+
+			toPoint.set( 7.5, -3.5, 0 );
+			toPoint.applyQuaternion( quaternion );
+			toPoint.add( point );
+
+			extrudeShape( tube1, fromPoint, toPoint );
+
+			fromPoint.set( -7, -3, 0 );
+			fromPoint.applyQuaternion( quaternion );
+			fromPoint.add( point );
+
+			toPoint.set( -7, -point.y, 0 );
+			toPoint.applyQuaternion( quaternion );
+			toPoint.add( point );
+
+			extrudeShape( tube2, fromPoint, toPoint );
+
+			fromPoint.set( 7, -3, 0 );
+			fromPoint.applyQuaternion( quaternion );
+			fromPoint.add( point );
+
+			toPoint.set( 7, -point.y, 0 );
+			toPoint.applyQuaternion( quaternion );
+			toPoint.add( point );
+
+			extrudeShape( tube3, fromPoint, toPoint );
+
+		} else {
+
+			fromPoint.set( 0, -2, 0 );
+			fromPoint.applyQuaternion( quaternion );
+			fromPoint.add( point );
+
+			toPoint.set( 0, -point.y, 0 );
+			toPoint.applyQuaternion( quaternion );
+			toPoint.add( point );
+
+			extrudeShape( tube3, fromPoint, toPoint );
+
+		}
+
+	}
+
+	this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+	this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( normals ), 3 ) );
+
+};
+
+RollerCoasterLiftersGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+
+var RollerCoasterShadowGeometry = function ( curve, size ) {
+
+	THREE.BufferGeometry.call( this );
+
+	var vertices = [];
+
+	var up = new THREE.Vector3( 0, 1, 0 );
+	var forward = new THREE.Vector3();
+
+	var quaternion = new THREE.Quaternion();
+	var prevQuaternion = new THREE.Quaternion();
+	prevQuaternion.setFromAxisAngle( up , Math.PI / 2 );
+
+	var point = new THREE.Vector3();
+
+	var prevPoint = new THREE.Vector3();
+	prevPoint.copy( curve.getPointAt( 0 ) );
+	prevPoint.y = 0;
+
+	var vector1 = new THREE.Vector3();
+	var vector2 = new THREE.Vector3();
+	var vector3 = new THREE.Vector3();
+	var vector4 = new THREE.Vector3();
+
+	for ( var i = 1; i <= size; i ++ ) {
+
+		point.copy( curve.getPointAt( i / size ) );
+		point.y = 0;
+
+		forward.subVectors( point, prevPoint );
+
+		var angle = Math.atan2( forward.x, forward.z );
+
+		quaternion.setFromAxisAngle( up, angle );
+
+		vector1.set( -3, 0, 0 );
+		vector1.applyQuaternion( quaternion );
+		vector1.add( point );
+
+		vector2.set(  3, 0, 0 );
+		vector2.applyQuaternion( quaternion );
+		vector2.add( point );
+
+		vector3.set(  3, 0, 0 );
+		vector3.applyQuaternion( prevQuaternion );
+		vector3.add( prevPoint );
+
+		vector4.set( -3, 0, 0 );
+		vector4.applyQuaternion( prevQuaternion );
+		vector4.add( prevPoint );
+
+		vertices.push( vector1.x, vector1.y, vector1.z );
+		vertices.push( vector2.x, vector2.y, vector2.z );
+		vertices.push( vector4.x, vector4.y, vector4.z );
+
+		vertices.push( vector2.x, vector2.y, vector2.z );
+		vertices.push( vector3.x, vector3.y, vector3.z );
+		vertices.push( vector4.x, vector4.y, vector4.z );
+
+		prevPoint.copy( point );
+		prevQuaternion.copy( quaternion );
+
+	}
+
+	this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+
+};
+
+RollerCoasterShadowGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+
+var SkyGeometry = function () {
+
+	THREE.BufferGeometry.call( this );
+
+	var vertices = [];
+
+	for ( var i = 0; i < 100; i ++ ) {
+
+		var x = Math.random() * 8000 - 4000;
+		var y = Math.random() * 500 + 500;
+		var z = Math.random() * 8000 - 4000;
+
+		var size = Math.random() * 400 + 200;
+
+		vertices.push( x - size, y, z - size );
+		vertices.push( x + size, y, z - size );
+		vertices.push( x - size, y, z + size );
+
+		vertices.push( x + size, y, z - size );
+		vertices.push( x + size, y, z + size );
+		vertices.push( x - size, y, z + size );
+
+	}
+
+
+	this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+
+};
+
+SkyGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+
+var TreesGeometry = function ( landscape ) {
+
+	THREE.BufferGeometry.call( this );
+
+	var vertices = [];
+	var colors = [];
+
+	var raycaster = new THREE.Raycaster();
+	raycaster.ray.direction.set( 0, -1, 0 );
+
+	for ( var i = 0; i < 2000; i ++ ) {
+
+		var x = Math.random() * 5000 - 2500;
+		var z = Math.random() * 5000 - 2500;
+
+		raycaster.ray.origin.set( x, 500, z );
+
+		var intersections = raycaster.intersectObject( landscape );
+
+		if ( intersections.length === 0 ) continue;
+
+		var y = intersections[ 0 ].point.y;
+
+		var height = Math.random() * 50 + 5;
+
+		var angle = Math.random() * Math.PI * 2;
+
+		vertices.push( x + Math.sin( angle ) * 10, y, z + Math.cos( angle ) * 10 );
+		vertices.push( x, y + height, z );
+		vertices.push( x + Math.sin( angle + Math.PI ) * 10, y, z + Math.cos( angle + Math.PI ) * 10 );
+
+		angle += Math.PI / 2;
+
+		vertices.push( x + Math.sin( angle ) * 10, y, z + Math.cos( angle ) * 10 );
+		vertices.push( x, y + height, z );
+		vertices.push( x + Math.sin( angle + Math.PI ) * 10, y, z + Math.cos( angle + Math.PI ) * 10 );
+
+		var random = Math.random() * 0.1;
+
+		for ( var j = 0; j < 6; j ++ ) {
+
+			colors.push( 0.2 + random, 0.4 + random, 0 );
+
+		}
+
+	}
+
+	this.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+	this.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
+
+};
+
+TreesGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );

+ 295 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderGodRays.js

@@ -0,0 +1,295 @@
+/**
+ * @author huwb / http://huwbowles.com/
+ *
+ * God-rays (crepuscular rays)
+ *
+ * Similar implementation to the one used by Crytek for CryEngine 2 [Sousa2008].
+ * Blurs a mask generated from the depth map along radial lines emanating from the light
+ * source. The blur repeatedly applies a blur filter of increasing support but constant
+ * sample count to produce a blur filter with large support.
+ *
+ * My implementation performs 3 passes, similar to the implementation from Sousa. I found
+ * just 6 samples per pass produced acceptible results. The blur is applied three times,
+ * with decreasing filter support. The result is equivalent to a single pass with
+ * 6*6*6 = 216 samples.
+ *
+ * References:
+ *
+ * Sousa2008 - Crysis Next Gen Effects, GDC2008, http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt
+ */
+
+THREE.ShaderGodRays = {
+
+	/**
+	 * The god-ray generation shader.
+	 *
+	 * First pass:
+	 *
+	 * The input is the depth map. I found that the output from the
+	 * THREE.MeshDepthMaterial material was directly suitable without
+	 * requiring any treatment whatsoever.
+	 *
+	 * The depth map is blurred along radial lines towards the "sun". The
+	 * output is written to a temporary render target (I used a 1/4 sized
+	 * target).
+	 *
+	 * Pass two & three:
+	 *
+	 * The results of the previous pass are re-blurred, each time with a
+	 * decreased distance between samples.
+	 */
+
+	'godrays_generate': {
+
+		uniforms: {
+
+			tInput: {
+				value: null
+			},
+			fStepSize: {
+				value: 1.0
+			},
+			vSunPositionScreenSpace: {
+				value: new THREE.Vector2( 0.5, 0.5 )
+			}
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+				"vUv = uv;",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"#define TAPS_PER_PASS 6.0",
+
+			"varying vec2 vUv;",
+
+			"uniform sampler2D tInput;",
+
+			"uniform vec2 vSunPositionScreenSpace;",
+			"uniform float fStepSize;", // filter step size
+
+			"void main() {",
+
+				// delta from current pixel to "sun" position
+
+				"vec2 delta = vSunPositionScreenSpace - vUv;",
+				"float dist = length( delta );",
+
+				// Step vector (uv space)
+
+				"vec2 stepv = fStepSize * delta / dist;",
+
+				// Number of iterations between pixel and sun
+
+				"float iters = dist/fStepSize;",
+
+				"vec2 uv = vUv.xy;",
+				"float col = 0.0;",
+
+				// This breaks ANGLE in Chrome 22
+				//	- see http://code.google.com/p/chromium/issues/detail?id=153105
+
+				/*
+				// Unrolling didnt do much on my hardware (ATI Mobility Radeon 3450),
+				// so i've just left the loop
+
+				"for ( float i = 0.0; i < TAPS_PER_PASS; i += 1.0 ) {",
+
+					// Accumulate samples, making sure we dont walk past the light source.
+
+					// The check for uv.y < 1 would not be necessary with "border" UV wrap
+					// mode, with a black border colour. I don't think this is currently
+					// exposed by three.js. As a result there might be artifacts when the
+					// sun is to the left, right or bottom of screen as these cases are
+					// not specifically handled.
+
+					"col += ( i <= iters && uv.y < 1.0 ? texture2D( tInput, uv ).r : 0.0 );",
+					"uv += stepv;",
+
+				"}",
+				*/
+
+				// Unrolling loop manually makes it work in ANGLE
+
+				"if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				"if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				"if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				"if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				"if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				"if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uv ).r;",
+				"uv += stepv;",
+
+				// Should technically be dividing by 'iters', but 'TAPS_PER_PASS' smooths out
+				// objectionable artifacts, in particular near the sun position. The side
+				// effect is that the result is darker than it should be around the sun, as
+				// TAPS_PER_PASS is greater than the number of samples actually accumulated.
+				// When the result is inverted (in the shader 'godrays_combine', this produces
+				// a slight bright spot at the position of the sun, even when it is occluded.
+
+				"gl_FragColor = vec4( col/TAPS_PER_PASS );",
+				"gl_FragColor.a = 1.0;",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	/**
+	 * Additively applies god rays from texture tGodRays to a background (tColors).
+	 * fGodRayIntensity attenuates the god rays.
+	 */
+
+	'godrays_combine': {
+
+		uniforms: {
+
+			tColors: {
+				value: null
+			},
+
+			tGodRays: {
+				value: null
+			},
+
+			fGodRayIntensity: {
+				value: 0.69
+			},
+
+			vSunPositionScreenSpace: {
+				value: new THREE.Vector2( 0.5, 0.5 )
+			}
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+				"vUv = uv;",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+			].join( "\n" ),
+
+		fragmentShader: [
+
+			"varying vec2 vUv;",
+
+			"uniform sampler2D tColors;",
+			"uniform sampler2D tGodRays;",
+
+			"uniform vec2 vSunPositionScreenSpace;",
+			"uniform float fGodRayIntensity;",
+
+			"void main() {",
+
+				// Since THREE.MeshDepthMaterial renders foreground objects white and background
+				// objects black, the god-rays will be white streaks. Therefore value is inverted
+				// before being combined with tColors
+
+				"gl_FragColor = texture2D( tColors, vUv ) + fGodRayIntensity * vec4( 1.0 - texture2D( tGodRays, vUv ).r );",
+				"gl_FragColor.a = 1.0;",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+
+	/**
+	 * A dodgy sun/sky shader. Makes a bright spot at the sun location. Would be
+	 * cheaper/faster/simpler to implement this as a simple sun sprite.
+	 */
+
+	'godrays_fake_sun': {
+
+		uniforms: {
+
+			vSunPositionScreenSpace: {
+				value: new THREE.Vector2( 0.5, 0.5 )
+			},
+
+			fAspect: {
+				value: 1.0
+			},
+
+			sunColor: {
+				value: new THREE.Color( 0xffee00 )
+			},
+
+			bgColor: {
+				value: new THREE.Color( 0x000000 )
+			}
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+				"vUv = uv;",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"varying vec2 vUv;",
+
+			"uniform vec2 vSunPositionScreenSpace;",
+			"uniform float fAspect;",
+
+			"uniform vec3 sunColor;",
+			"uniform vec3 bgColor;",
+
+			"void main() {",
+
+				"vec2 diff = vUv - vSunPositionScreenSpace;",
+
+				// Correct for aspect ratio
+
+				"diff.x *= fAspect;",
+
+				"float prop = clamp( length( diff ) / 0.5, 0.0, 1.0 );",
+				"prop = 0.35 * pow( 1.0 - prop, 3.0 );",
+
+				"gl_FragColor.xyz = mix( sunColor, bgColor, 1.0 - prop );",
+				"gl_FragColor.w = 1.0;",
+
+			"}"
+
+		].join( "\n" )
+
+	}
+
+};

+ 692 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderSkin.js

@@ -0,0 +1,692 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ *
+ */
+
+
+THREE.ShaderSkin = {
+
+	/* ------------------------------------------------------------------------------------------
+	//	Simple skin shader
+	//		- per-pixel Blinn-Phong diffuse term mixed with half-Lambert wrap-around term (per color component)
+	//		- physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
+	//
+	//		- diffuse map
+	//		- bump map
+	//		- specular map
+	//		- point, directional and hemisphere lights (use with "lights: true" material option)
+	//		- fog (use with "fog: true" material option)
+	//		- shadow maps
+	//
+	// ------------------------------------------------------------------------------------------ */
+
+	'skinSimple' : {
+
+		uniforms: THREE.UniformsUtils.merge( [
+
+			THREE.UniformsLib[ "fog" ],
+			THREE.UniformsLib[ "lights" ],
+
+			{
+
+				"enableBump": { value: 0 },
+				"enableSpecular": { value: 0 },
+
+				"tDiffuse": { value: null },
+				"tBeckmann": { value: null },
+
+				"diffuse": { value: new THREE.Color( 0xeeeeee ) },
+				"specular": { value: new THREE.Color( 0x111111 ) },
+				"opacity": { value: 1 },
+
+				"uRoughness": { value: 0.15 },
+				"uSpecularBrightness": { value: 0.75 },
+
+				"bumpMap": { value: null },
+				"bumpScale": { value: 1 },
+
+				"specularMap": { value: null },
+
+				"offsetRepeat": { value: new THREE.Vector4( 0, 0, 1, 1 ) },
+
+				"uWrapRGB": { value: new THREE.Vector3( 0.75, 0.375, 0.1875 ) }
+
+			}
+
+		] ),
+
+		fragmentShader: [
+
+			"#define USE_BUMPMAP",
+
+			"uniform bool enableBump;",
+			"uniform bool enableSpecular;",
+
+			"uniform vec3 diffuse;",
+			"uniform vec3 specular;",
+			"uniform float opacity;",
+
+			"uniform float uRoughness;",
+			"uniform float uSpecularBrightness;",
+
+			"uniform vec3 uWrapRGB;",
+
+			"uniform sampler2D tDiffuse;",
+			"uniform sampler2D tBeckmann;",
+
+			"uniform sampler2D specularMap;",
+
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+			THREE.ShaderChunk[ "bsdfs" ],
+			THREE.ShaderChunk[ "packing" ],
+			THREE.ShaderChunk[ "lights_pars" ],
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
+			THREE.ShaderChunk[ "fog_pars_fragment" ],
+			THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
+
+			// Fresnel term
+
+			"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
+
+				"float base = 1.0 - dot( V, H );",
+				"float exponential = pow( base, 5.0 );",
+
+				"return exponential + F0 * ( 1.0 - exponential );",
+
+			"}",
+
+			// Kelemen/Szirmay-Kalos specular BRDF
+
+			"float KS_Skin_Specular( vec3 N,", 		// Bumped surface normal
+									"vec3 L,", 		// Points to light
+									"vec3 V,", 		// Points to eye
+									"float m,",  	// Roughness
+									"float rho_s", 	// Specular brightness
+									") {",
+
+				"float result = 0.0;",
+				"float ndotl = dot( N, L );",
+
+				"if( ndotl > 0.0 ) {",
+
+					"vec3 h = L + V;", // Unnormalized half-way vector
+					"vec3 H = normalize( h );",
+
+					"float ndoth = dot( N, H );",
+
+					"float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
+
+					"float F = fresnelReflectance( H, V, 0.028 );",
+					"float frSpec = max( PH * F / dot( h, h ), 0.0 );",
+
+					"result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
+
+				"}",
+
+				"return result;",
+
+			"}",
+
+			"void main() {",
+
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
+
+				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
+				"colDiffuse.rgb *= colDiffuse.rgb;",
+
+				"diffuseColor = diffuseColor * colDiffuse;",
+
+				"vec3 normal = normalize( vNormal );",
+				"vec3 viewerDirection = normalize( vViewPosition );",
+
+				"float specularStrength;",
+
+				"if ( enableSpecular ) {",
+
+					"vec4 texelSpecular = texture2D( specularMap, vUv );",
+					"specularStrength = texelSpecular.r;",
+
+				"} else {",
+
+					"specularStrength = 1.0;",
+
+				"}",
+
+				"#ifdef USE_BUMPMAP",
+
+					"if ( enableBump ) normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
+
+				"#endif",
+
+				// point lights
+
+				"vec3 totalSpecularLight = vec3( 0.0 );",
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
+
+				"#if NUM_POINT_LIGHTS > 0",
+
+					"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
+
+						"vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
+
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
+
+						"lVector = normalize( lVector );",
+
+						"float pointDiffuseWeightFull = max( dot( normal, lVector ), 0.0 );",
+						"float pointDiffuseWeightHalf = max( 0.5 * dot( normal, lVector ) + 0.5, 0.0 );",
+						"vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), uWrapRGB );",
+
+						"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewerDirection, uRoughness, uSpecularBrightness );",
+
+						"totalDiffuseLight += pointLight[ i ].color * ( pointDiffuseWeight * attenuation );",
+						"totalSpecularLight += pointLight[ i ].color * specular * ( pointSpecularWeight * specularStrength * attenuation );",
+
+					"}",
+
+				"#endif",
+
+				// directional lights
+
+				"#if NUM_DIR_LIGHTS > 0",
+
+					"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
+
+						"vec3 dirVector = directionalLights[ i ].direction;",
+
+						"float dirDiffuseWeightFull = max( dot( normal, dirVector ), 0.0 );",
+						"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
+						"vec3 dirDiffuseWeight = mix( vec3 ( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), uWrapRGB );",
+
+						"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
+
+						"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
+						"totalSpecularLight += directionalLights[ i ].color * ( dirSpecularWeight * specularStrength );",
+
+					"}",
+
+				"#endif",
+
+				// hemisphere lights
+
+				"#if NUM_HEMI_LIGHTS > 0",
+
+					"for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {",
+
+						"vec3 lVector = hemisphereLightDirection[ i ];",
+
+						"float dotProduct = dot( normal, lVector );",
+						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+
+						"totalDiffuseLight += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+
+						// specular (sky light)
+
+						"float hemiSpecularWeight = 0.0;",
+						"hemiSpecularWeight += KS_Skin_Specular( normal, lVector, viewerDirection, uRoughness, uSpecularBrightness );",
+
+						// specular (ground light)
+
+						"vec3 lVectorGround = -lVector;",
+						"hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewerDirection, uRoughness, uSpecularBrightness );",
+
+						"vec3 hemiSpecularColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+
+						"totalSpecularLight += hemiSpecularColor * specular * ( hemiSpecularWeight * specularStrength );",
+
+					"}",
+
+				"#endif",
+
+				"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * diffuse ) + totalSpecularLight;",
+
+				"gl_FragColor = linearToOutputTexel( vec4( outgoingLight, diffuseColor.a ) );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
+				THREE.ShaderChunk[ "fog_fragment" ],
+
+			"}"
+
+		].join( "\n" ),
+
+		vertexShader: [
+
+			"uniform vec4 offsetRepeat;",
+
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+			THREE.ShaderChunk[ "lights_pars" ],
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+
+			"void main() {",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+
+				"vViewPosition = -mvPosition.xyz;",
+
+				"vNormal = normalize( normalMatrix * normal );",
+
+				"vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
+
+				"gl_Position = projectionMatrix * mvPosition;",
+
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	/* ------------------------------------------------------------------------------------------
+	//	Skin shader
+	//		- Blinn-Phong diffuse term (using normal + diffuse maps)
+	//		- subsurface scattering approximation by four blur layers
+	//		- physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
+	//
+	//		- point and directional lights (use with "lights: true" material option)
+	//
+	//		- based on Nvidia Advanced Skin Rendering GDC 2007 presentation
+	//		  and GPU Gems 3 Chapter 14. Advanced Techniques for Realistic Real-Time Skin Rendering
+	//
+	//			http://developer.download.nvidia.com/presentations/2007/gdc/Advanced_Skin.pdf
+	//			http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html
+	// ------------------------------------------------------------------------------------------ */
+
+	'skin' : {
+
+		uniforms: THREE.UniformsUtils.merge( [
+
+			THREE.UniformsLib[ "fog" ],
+			THREE.UniformsLib[ "lights" ],
+
+			{
+
+				"passID": { value: 0 },
+
+				"tDiffuse"	: { value: null },
+				"tNormal"	: { value: null },
+
+				"tBlur1"	: { value: null },
+				"tBlur2"	: { value: null },
+				"tBlur3"	: { value: null },
+				"tBlur4"	: { value: null },
+
+				"tBeckmann"	: { value: null },
+
+				"uNormalScale": { value: 1.0 },
+
+				"diffuse":  { value: new THREE.Color( 0xeeeeee ) },
+				"specular": { value: new THREE.Color( 0x111111 ) },
+				"opacity": 	  { value: 1 },
+
+				"uRoughness": 	  		{ value: 0.15 },
+				"uSpecularBrightness": 	{ value: 0.75 }
+
+			}
+
+		] ),
+
+		fragmentShader: [
+
+			"uniform vec3 diffuse;",
+			"uniform vec3 specular;",
+			"uniform float opacity;",
+
+			"uniform float uRoughness;",
+			"uniform float uSpecularBrightness;",
+
+			"uniform int passID;",
+
+			"uniform sampler2D tDiffuse;",
+			"uniform sampler2D tNormal;",
+
+			"uniform sampler2D tBlur1;",
+			"uniform sampler2D tBlur2;",
+			"uniform sampler2D tBlur3;",
+			"uniform sampler2D tBlur4;",
+
+			"uniform sampler2D tBeckmann;",
+
+			"uniform float uNormalScale;",
+
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+			THREE.ShaderChunk[ "lights_pars" ],
+			THREE.ShaderChunk[ "fog_pars_fragment" ],
+
+			"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
+
+				"float base = 1.0 - dot( V, H );",
+				"float exponential = pow( base, 5.0 );",
+
+				"return exponential + F0 * ( 1.0 - exponential );",
+
+			"}",
+
+			// Kelemen/Szirmay-Kalos specular BRDF
+
+			"float KS_Skin_Specular( vec3 N,", 		// Bumped surface normal
+									"vec3 L,", 		// Points to light
+									"vec3 V,", 		// Points to eye
+									"float m,",  	// Roughness
+									"float rho_s", 	// Specular brightness
+									") {",
+
+				"float result = 0.0;",
+				"float ndotl = dot( N, L );",
+
+				"if( ndotl > 0.0 ) {",
+
+					"vec3 h = L + V;", // Unnormalized half-way vector
+					"vec3 H = normalize( h );",
+
+					"float ndoth = dot( N, H );",
+
+					"float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
+					"float F = fresnelReflectance( H, V, 0.028 );",
+					"float frSpec = max( PH * F / dot( h, h ), 0.0 );",
+
+					"result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
+
+				"}",
+
+				"return result;",
+
+			"}",
+
+			"void main() {",
+
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
+
+				"vec4 mSpecular = vec4( specular, opacity );",
+
+				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
+				"colDiffuse *= colDiffuse;",
+
+				"diffuseColor *= colDiffuse;",
+
+				// normal mapping
+
+				"vec4 posAndU = vec4( -vViewPosition, vUv.x );",
+				"vec4 posAndU_dx = dFdx( posAndU ),  posAndU_dy = dFdy( posAndU );",
+				"vec3 tangent = posAndU_dx.w * posAndU_dx.xyz + posAndU_dy.w * posAndU_dy.xyz;",
+				"vec3 normal = normalize( vNormal );",
+				"vec3 binormal = normalize( cross( tangent, normal ) );",
+				"tangent = cross( normal, binormal );",	// no normalization required
+				"mat3 tsb = mat3( tangent, binormal, normal );",
+
+				"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
+				"normalTex.xy *= uNormalScale;",
+				"normalTex = normalize( normalTex );",
+
+				"vec3 finalNormal = tsb * normalTex;",
+				"normal = normalize( finalNormal );",
+
+				"vec3 viewerDirection = normalize( vViewPosition );",
+
+				// point lights
+
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
+				"vec3 totalSpecularLight = vec3( 0.0 );",
+
+				"#if NUM_POINT_LIGHTS > 0",
+
+					"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
+
+						"vec3 pointVector = normalize( pointLights[ i ].direction );",
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
+
+						"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
+
+						"totalDiffuseLight += pointLightColor[ i ] * ( pointDiffuseWeight * attenuation );",
+
+						"if ( passID == 1 ) {",
+
+							"float pointSpecularWeight = KS_Skin_Specular( normal, pointVector, viewerDirection, uRoughness, uSpecularBrightness );",
+
+							"totalSpecularLight += pointLightColor[ i ] * mSpecular.xyz * ( pointSpecularWeight * attenuation );",
+
+						"}",
+
+					"}",
+
+				"#endif",
+
+				// directional lights
+
+				"#if NUM_DIR_LIGHTS > 0",
+
+					"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
+
+						"vec3 dirVector = directionalLights[ i ].direction;",
+
+						"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
+
+
+						"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
+
+						"if ( passID == 1 ) {",
+
+							"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
+
+							"totalSpecularLight += directionalLights[ i ].color * mSpecular.xyz * dirSpecularWeight;",
+
+						"}",
+
+					"}",
+
+				"#endif",
+
+
+				"outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalSpecularLight );",
+
+				"if ( passID == 0 ) {",
+
+					"outgoingLight = sqrt( outgoingLight );",
+
+				"} else if ( passID == 1 ) {",
+
+					//"#define VERSION1",
+
+					"#ifdef VERSION1",
+
+						"vec3 nonblurColor = sqrt(outgoingLight );",
+
+					"#else",
+
+						"vec3 nonblurColor = outgoingLight;",
+
+					"#endif",
+
+					"vec3 blur1Color = texture2D( tBlur1, vUv ).xyz;",
+					"vec3 blur2Color = texture2D( tBlur2, vUv ).xyz;",
+					"vec3 blur3Color = texture2D( tBlur3, vUv ).xyz;",
+					"vec3 blur4Color = texture2D( tBlur4, vUv ).xyz;",
+
+
+					//"gl_FragColor = vec4( blur1Color, gl_FragColor.w );",
+
+					//"gl_FragColor = vec4( vec3( 0.22, 0.5, 0.7 ) * nonblurColor + vec3( 0.2, 0.5, 0.3 ) * blur1Color + vec3( 0.58, 0.0, 0.0 ) * blur2Color, gl_FragColor.w );",
+
+					//"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
+
+
+					"outgoingLight = vec3( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
+										 "vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
+										 "vec3( 0.119, 0.208, 0.0 )   * blur2Color + ",
+										 "vec3( 0.114, 0.0,   0.0 )   * blur3Color + ",
+										 "vec3( 0.444, 0.0,   0.0 )   * blur4Color );",
+
+					"outgoingLight *= sqrt( colDiffuse.xyz );",
+
+					"outgoingLight += ambientLightColor * diffuse * colDiffuse.xyz + totalSpecularLight;",
+
+					"#ifndef VERSION1",
+
+						"outgoingLight = sqrt( outgoingLight );",
+
+					"#endif",
+
+				"}",
+
+				"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
+				THREE.ShaderChunk[ "fog_fragment" ],
+
+			"}"
+
+		].join( "\n" ),
+
+		vertexShader: [
+
+			"#ifdef VERTEX_TEXTURES",
+
+				"uniform sampler2D tDisplacement;",
+				"uniform float uDisplacementScale;",
+				"uniform float uDisplacementBias;",
+
+			"#endif",
+
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+
+			"void main() {",
+
+				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+
+				"vViewPosition = -mvPosition.xyz;",
+
+				"vNormal = normalize( normalMatrix * normal );",
+
+				"vUv = uv;",
+
+				// displacement mapping
+
+				"#ifdef VERTEX_TEXTURES",
+
+					"vec3 dv = texture2D( tDisplacement, uv ).xyz;",
+					"float df = uDisplacementScale * dv.x + uDisplacementBias;",
+					"vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
+					"gl_Position = projectionMatrix * displacedPosition;",
+
+				"#else",
+
+					"gl_Position = projectionMatrix * mvPosition;",
+
+				"#endif",
+
+			"}"
+
+		].join( "\n" ),
+
+		vertexShaderUV: [
+
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+
+			"void main() {",
+
+				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+
+				"vViewPosition = -mvPosition.xyz;",
+
+				"vNormal = normalize( normalMatrix * normal );",
+
+				"vUv = uv;",
+
+				"gl_Position = vec4( uv.x * 2.0 - 1.0, uv.y * 2.0 - 1.0, 0.0, 1.0 );",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	/* ------------------------------------------------------------------------------------------
+	// Beckmann distribution function
+	//	- to be used in specular term of skin shader
+	//	- render a screen-aligned quad to precompute a 512 x 512 texture
+	//
+	//		- from http://developer.nvidia.com/node/171
+	 ------------------------------------------------------------------------------------------ */
+
+	"beckmann" : {
+
+		uniforms: {},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+				"vUv = uv;",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"varying vec2 vUv;",
+
+			"float PHBeckmann( float ndoth, float m ) {",
+
+				"float alpha = acos( ndoth );",
+				"float ta = tan( alpha );",
+
+				"float val = 1.0 / ( m * m * pow( ndoth, 4.0 ) ) * exp( -( ta * ta ) / ( m * m ) );",
+				"return val;",
+
+			"}",
+
+			"float KSTextureCompute( vec2 tex ) {",
+
+				// Scale the value to fit within [0,1]  invert upon lookup.
+
+				"return 0.5 * pow( PHBeckmann( tex.x, tex.y ), 0.1 );",
+
+			"}",
+
+			"void main() {",
+
+				"float x = KSTextureCompute( vUv );",
+
+				"gl_FragColor = vec4( x, x, x, 1.0 );",
+
+			"}"
+
+		].join( "\n" )
+
+	}
+
+};

+ 322 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderTerrain.js

@@ -0,0 +1,322 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ *
+ */
+
+THREE.ShaderTerrain = {
+
+	/* -------------------------------------------------------------------------
+	//	Dynamic terrain shader
+	//		- Blinn-Phong
+	//		- height + normal + diffuse1 + diffuse2 + specular + detail maps
+	//		- point, directional and hemisphere lights (use with "lights: true" material option)
+	//		- shadow maps receiving
+	 ------------------------------------------------------------------------- */
+
+	'terrain' : {
+
+		uniforms: THREE.UniformsUtils.merge( [
+
+			THREE.UniformsLib[ "fog" ],
+			THREE.UniformsLib[ "lights" ],
+
+			{
+
+				"enableDiffuse1": { value: 0 },
+				"enableDiffuse2": { value: 0 },
+				"enableSpecular": { value: 0 },
+				"enableReflection": { value: 0 },
+
+				"tDiffuse1": { value: null },
+				"tDiffuse2": { value: null },
+				"tDetail": { value: null },
+				"tNormal": { value: null },
+				"tSpecular": { value: null },
+				"tDisplacement": { value: null },
+
+				"uNormalScale": { value: 1.0 },
+
+				"uDisplacementBias": { value: 0.0 },
+				"uDisplacementScale": { value: 1.0 },
+
+				"diffuse": { value: new THREE.Color( 0xeeeeee ) },
+				"specular": { value: new THREE.Color( 0x111111 ) },
+				"shininess": { value: 30 },
+				"opacity": { value: 1 },
+
+				"uRepeatBase": { value: new THREE.Vector2( 1, 1 ) },
+				"uRepeatOverlay": { value: new THREE.Vector2( 1, 1 ) },
+
+				"uOffset": { value: new THREE.Vector2( 0, 0 ) }
+
+			}
+
+		] ),
+
+		fragmentShader: [
+
+			"uniform vec3 diffuse;",
+			"uniform vec3 specular;",
+			"uniform float shininess;",
+			"uniform float opacity;",
+
+			"uniform bool enableDiffuse1;",
+			"uniform bool enableDiffuse2;",
+			"uniform bool enableSpecular;",
+
+			"uniform sampler2D tDiffuse1;",
+			"uniform sampler2D tDiffuse2;",
+			"uniform sampler2D tDetail;",
+			"uniform sampler2D tNormal;",
+			"uniform sampler2D tSpecular;",
+			"uniform sampler2D tDisplacement;",
+
+			"uniform float uNormalScale;",
+
+			"uniform vec2 uRepeatOverlay;",
+			"uniform vec2 uRepeatBase;",
+
+			"uniform vec2 uOffset;",
+
+			"varying vec3 vTangent;",
+			"varying vec3 vBinormal;",
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "common" ],
+			THREE.ShaderChunk[ "bsdfs" ],
+			THREE.ShaderChunk[ "lights_pars" ],
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
+			THREE.ShaderChunk[ "fog_pars_fragment" ],
+
+			"float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {",
+ 				"if ( decayExponent > 0.0 ) {",
+ 					"return pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );",
+ 				"}",
+ 				"return 1.0;",
+ 			"}",
+
+			"void main() {",
+
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
+
+				"vec3 specularTex = vec3( 1.0 );",
+
+				"vec2 uvOverlay = uRepeatOverlay * vUv + uOffset;",
+				"vec2 uvBase = uRepeatBase * vUv;",
+
+				"vec3 normalTex = texture2D( tDetail, uvOverlay ).xyz * 2.0 - 1.0;",
+				"normalTex.xy *= uNormalScale;",
+				"normalTex = normalize( normalTex );",
+
+				"if( enableDiffuse1 && enableDiffuse2 ) {",
+
+					"vec4 colDiffuse1 = texture2D( tDiffuse1, uvOverlay );",
+					"vec4 colDiffuse2 = texture2D( tDiffuse2, uvOverlay );",
+
+					"colDiffuse1 = GammaToLinear( colDiffuse1, float( GAMMA_FACTOR ) );",
+					"colDiffuse2 = GammaToLinear( colDiffuse2, float( GAMMA_FACTOR ) );",
+
+					"diffuseColor *= mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
+
+				" } else if( enableDiffuse1 ) {",
+
+					"diffuseColor *= texture2D( tDiffuse1, uvOverlay );",
+
+				"} else if( enableDiffuse2 ) {",
+
+					"diffuseColor *= texture2D( tDiffuse2, uvOverlay );",
+
+				"}",
+
+				"if( enableSpecular )",
+					"specularTex = texture2D( tSpecular, uvOverlay ).xyz;",
+
+				"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
+				"vec3 finalNormal = tsb * normalTex;",
+
+				"vec3 normal = normalize( finalNormal );",
+				"vec3 viewPosition = normalize( vViewPosition );",
+
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
+				"vec3 totalSpecularLight = vec3( 0.0 );",
+
+				// point lights
+
+				"#if NUM_POINT_LIGHTS > 0",
+
+					"for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {",
+
+						"vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
+
+						"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
+
+						"lVector = normalize( lVector );",
+
+						"vec3 pointHalfVector = normalize( lVector + viewPosition );",
+
+						"float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
+						"float pointDiffuseWeight = max( dot( normal, lVector ), 0.0 );",
+
+						"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
+
+						"totalDiffuseLight += attenuation * pointLights[ i ].color * pointDiffuseWeight;",
+						"totalSpecularLight += attenuation * pointLights[ i ].color * specular * pointSpecularWeight * pointDiffuseWeight;",
+
+					"}",
+
+				"#endif",
+
+				// directional lights
+
+				"#if NUM_DIR_LIGHTS > 0",
+
+					"vec3 dirDiffuse = vec3( 0.0 );",
+					"vec3 dirSpecular = vec3( 0.0 );",
+
+					"for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {",
+
+						"vec3 dirVector = directionalLights[ i ].direction;",
+						"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
+
+						"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
+						"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
+
+						"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
+
+						"totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
+						"totalSpecularLight += directionalLights[ i ].color * specular * dirSpecularWeight * dirDiffuseWeight;",
+
+					"}",
+
+				"#endif",
+
+				// hemisphere lights
+
+				"#if NUM_HEMI_LIGHTS > 0",
+
+					"vec3 hemiDiffuse  = vec3( 0.0 );",
+					"vec3 hemiSpecular = vec3( 0.0 );",
+
+					"for( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {",
+
+						"vec3 lVector = hemisphereLightDirection[ i ];",
+
+						// diffuse
+
+						"float dotProduct = dot( normal, lVector );",
+						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+
+						"totalDiffuseLight += mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight );",
+
+						// specular (sky light)
+
+						"float hemiSpecularWeight = 0.0;",
+
+						"vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
+						"float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
+						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );",
+
+						// specular (ground light)
+
+						"vec3 lVectorGround = -lVector;",
+
+						"vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
+						"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
+						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
+
+						"totalSpecularLight += specular * mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
+
+					"}",
+
+				"#endif",
+
+				"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor + totalSpecularLight );",
+
+				"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
+				THREE.ShaderChunk[ "fog_fragment" ],
+
+			"}"
+
+		].join( "\n" ),
+
+		vertexShader: [
+
+			"attribute vec4 tangent;",
+
+			"uniform vec2 uRepeatBase;",
+
+			"uniform sampler2D tNormal;",
+
+			"#ifdef VERTEX_TEXTURES",
+
+				"uniform sampler2D tDisplacement;",
+				"uniform float uDisplacementScale;",
+				"uniform float uDisplacementBias;",
+
+			"#endif",
+
+			"varying vec3 vTangent;",
+			"varying vec3 vBinormal;",
+			"varying vec3 vNormal;",
+			"varying vec2 vUv;",
+
+			"varying vec3 vViewPosition;",
+
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
+
+			"void main() {",
+
+				"vNormal = normalize( normalMatrix * normal );",
+
+				// tangent and binormal vectors
+
+				"vTangent = normalize( normalMatrix * tangent.xyz );",
+
+				"vBinormal = cross( vNormal, vTangent ) * tangent.w;",
+				"vBinormal = normalize( vBinormal );",
+
+				// texture coordinates
+
+				"vUv = uv;",
+
+				"vec2 uvBase = uv * uRepeatBase;",
+
+				// displacement mapping
+
+				"#ifdef VERTEX_TEXTURES",
+
+					"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",
+					"float df = uDisplacementScale * dv.x + uDisplacementBias;",
+					"vec3 displacedPosition = normal * df + position;",
+
+					"vec4 worldPosition = modelMatrix * vec4( displacedPosition, 1.0 );",
+					"vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );",
+
+				"#else",
+
+					"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+					"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+
+				"#endif",
+
+				"gl_Position = projectionMatrix * mvPosition;",
+
+				"vViewPosition = -mvPosition.xyz;",
+
+				"vec3 normalTex = texture2D( tNormal, uvBase ).xyz * 2.0 - 1.0;",
+				"vNormal = normalMatrix * normalTex;",
+
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
+
+			"}"
+
+		].join( "\n" )
+
+	}
+
+};

+ 331 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/ShaderToon.js

@@ -0,0 +1,331 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ *
+ * ShaderToon currently contains:
+ *
+ *	toon1
+ *	toon2
+ *	hatching
+ *	dotted
+ */
+
+THREE.ShaderToon = {
+
+	'toon1' : {
+
+		uniforms: {
+
+			"uDirLightPos": { value: new THREE.Vector3() },
+			"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
+
+			"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
+
+			"uBaseColor": { value: new THREE.Color( 0xffffff ) }
+
+		},
+
+		vertexShader: [
+
+			"varying vec3 vNormal;",
+			"varying vec3 vRefract;",
+
+			"void main() {",
+
+				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
+
+				"vNormal = normalize( normalMatrix * normal );",
+
+				"vec3 I = worldPosition.xyz - cameraPosition;",
+				"vRefract = refract( normalize( I ), worldNormal, 1.02 );",
+
+				"gl_Position = projectionMatrix * mvPosition;",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform vec3 uBaseColor;",
+
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
+
+			"uniform vec3 uAmbientLightColor;",
+
+			"varying vec3 vNormal;",
+
+			"varying vec3 vRefract;",
+
+			"void main() {",
+
+				"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+
+				"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
+				"intensity += length(lightWeighting) * 0.2;",
+
+				"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
+				"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
+				"intensity = intensity * 0.2 + 0.3;",
+
+				"if ( intensity < 0.50 ) {",
+
+					"gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
+
+				"} else {",
+
+					"gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
+
+				"}",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	'toon2' : {
+
+		uniforms: {
+
+			"uDirLightPos": { value: new THREE.Vector3() },
+			"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
+
+			"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
+
+			"uBaseColor": { value: new THREE.Color( 0xeeeeee ) },
+			"uLineColor1": { value: new THREE.Color( 0x808080 ) },
+			"uLineColor2": { value: new THREE.Color( 0x000000 ) },
+			"uLineColor3": { value: new THREE.Color( 0x000000 ) },
+			"uLineColor4": { value: new THREE.Color( 0x000000 ) }
+
+		},
+
+		vertexShader: [
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
+
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
+
+			"uniform vec3 uAmbientLightColor;",
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4);",
+				"float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
+
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
+
+				"if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) {",
+
+					"gl_FragColor *= vec4( uLineColor1, 1.0 );",
+
+				"}",
+
+				"if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) {",
+
+					"gl_FragColor *= vec4( uLineColor2, 1.0 );",
+
+				"}",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	'hatching' : {
+
+		uniforms: {
+
+			"uDirLightPos":	{ value: new THREE.Vector3() },
+			"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
+
+			"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
+
+			"uBaseColor":  { value: new THREE.Color( 0xffffff ) },
+			"uLineColor1": { value: new THREE.Color( 0x000000 ) },
+			"uLineColor2": { value: new THREE.Color( 0x000000 ) },
+			"uLineColor3": { value: new THREE.Color( 0x000000 ) },
+			"uLineColor4": { value: new THREE.Color( 0x000000 ) }
+
+		},
+
+		vertexShader: [
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
+
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
+
+			"uniform vec3 uAmbientLightColor;",
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
+
+				"if ( length(lightWeighting) < 1.00 ) {",
+
+					"if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {",
+
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
+
+					"}",
+
+				"}",
+
+				"if ( length(lightWeighting) < 0.75 ) {",
+
+					"if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {",
+
+						"gl_FragColor = vec4( uLineColor2, 1.0 );",
+
+					"}",
+				"}",
+
+				"if ( length(lightWeighting) < 0.50 ) {",
+
+					"if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
+
+						"gl_FragColor = vec4( uLineColor3, 1.0 );",
+
+					"}",
+				"}",
+
+				"if ( length(lightWeighting) < 0.3465 ) {",
+
+					"if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
+
+						"gl_FragColor = vec4( uLineColor4, 1.0 );",
+
+					"}",
+				"}",
+
+			"}"
+
+		].join( "\n" )
+
+	},
+
+	'dotted' : {
+
+		uniforms: {
+
+			"uDirLightPos":	{ value: new THREE.Vector3() },
+			"uDirLightColor": { value: new THREE.Color( 0xeeeeee ) },
+
+			"uAmbientLightColor": { value: new THREE.Color( 0x050505 ) },
+
+			"uBaseColor":  { value: new THREE.Color( 0xffffff ) },
+			"uLineColor1": { value: new THREE.Color( 0x000000 ) }
+
+		},
+
+		vertexShader: [
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
+
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
+
+			"uniform vec3 uAmbientLightColor;",
+
+			"varying vec3 vNormal;",
+
+			"void main() {",
+
+				"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
+
+				"if ( length(lightWeighting) < 1.00 ) {",
+
+					"if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) {",
+
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
+
+					"}",
+
+				"}",
+
+				"if ( length(lightWeighting) < 0.50 ) {",
+
+					"if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) {",
+
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
+
+					"}",
+
+				"}",
+
+			"}"
+
+		].join( "\n" )
+
+	}
+
+};

+ 324 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/SimplexNoise.js

@@ -0,0 +1,324 @@
+// Ported from Stefan Gustavson's java implementation
+// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
+// Read Stefan's excellent paper for details on how this code works.
+//
+// Sean McCullough banksean@gmail.com
+//
+// Added 4D noise
+// Joshua Koo zz85nus@gmail.com 
+
+/**
+ * You can pass in a random number generator object if you like.
+ * It is assumed to have a random() method.
+ */
+var SimplexNoise = function(r) {
+	if (r == undefined) r = Math;
+	this.grad3 = [[ 1,1,0 ],[ -1,1,0 ],[ 1,-1,0 ],[ -1,-1,0 ], 
+                                 [ 1,0,1 ],[ -1,0,1 ],[ 1,0,-1 ],[ -1,0,-1 ], 
+                                 [ 0,1,1 ],[ 0,-1,1 ],[ 0,1,-1 ],[ 0,-1,-1 ]]; 
+
+	this.grad4 = [[ 0,1,1,1 ], [ 0,1,1,-1 ], [ 0,1,-1,1 ], [ 0,1,-1,-1 ],
+	     [ 0,-1,1,1 ], [ 0,-1,1,-1 ], [ 0,-1,-1,1 ], [ 0,-1,-1,-1 ],
+	     [ 1,0,1,1 ], [ 1,0,1,-1 ], [ 1,0,-1,1 ], [ 1,0,-1,-1 ],
+	     [ -1,0,1,1 ], [ -1,0,1,-1 ], [ -1,0,-1,1 ], [ -1,0,-1,-1 ],
+	     [ 1,1,0,1 ], [ 1,1,0,-1 ], [ 1,-1,0,1 ], [ 1,-1,0,-1 ],
+	     [ -1,1,0,1 ], [ -1,1,0,-1 ], [ -1,-1,0,1 ], [ -1,-1,0,-1 ],
+	     [ 1,1,1,0 ], [ 1,1,-1,0 ], [ 1,-1,1,0 ], [ 1,-1,-1,0 ],
+	     [ -1,1,1,0 ], [ -1,1,-1,0 ], [ -1,-1,1,0 ], [ -1,-1,-1,0 ]];
+
+	this.p = [];
+	for (var i = 0; i < 256; i ++) {
+		this.p[i] = Math.floor(r.random() * 256);
+	}
+  // To remove the need for index wrapping, double the permutation table length 
+	this.perm = []; 
+	for (var i = 0; i < 512; i ++) {
+		this.perm[i] = this.p[i & 255];
+	} 
+
+  // A lookup table to traverse the simplex around a given point in 4D. 
+  // Details can be found where this table is used, in the 4D noise method. 
+	this.simplex = [ 
+    [ 0,1,2,3 ],[ 0,1,3,2 ],[ 0,0,0,0 ],[ 0,2,3,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,2,3,0 ], 
+    [ 0,2,1,3 ],[ 0,0,0,0 ],[ 0,3,1,2 ],[ 0,3,2,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,3,2,0 ], 
+    [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ], 
+    [ 1,2,0,3 ],[ 0,0,0,0 ],[ 1,3,0,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,3,0,1 ],[ 2,3,1,0 ], 
+    [ 1,0,2,3 ],[ 1,0,3,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,0,3,1 ],[ 0,0,0,0 ],[ 2,1,3,0 ], 
+    [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ], 
+    [ 2,0,1,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,0,1,2 ],[ 3,0,2,1 ],[ 0,0,0,0 ],[ 3,1,2,0 ], 
+    [ 2,1,0,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,1,0,2 ],[ 0,0,0,0 ],[ 3,2,0,1 ],[ 3,2,1,0 ]]; 
+};
+
+SimplexNoise.prototype.dot = function(g, x, y) { 
+	return g[0] * x + g[1] * y;
+};
+
+SimplexNoise.prototype.dot3 = function(g, x, y, z) {
+	return g[0] * x + g[1] * y + g[2] * z; 
+};
+
+SimplexNoise.prototype.dot4 = function(g, x, y, z, w) {
+	return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
+};
+
+SimplexNoise.prototype.noise = function(xin, yin) { 
+	var n0, n1, n2; // Noise contributions from the three corners 
+  // Skew the input space to determine which simplex cell we're in 
+	var F2 = 0.5 * (Math.sqrt(3.0) - 1.0); 
+	var s = (xin + yin) * F2; // Hairy factor for 2D 
+	var i = Math.floor(xin + s); 
+	var j = Math.floor(yin + s); 
+	var G2 = (3.0 - Math.sqrt(3.0)) / 6.0; 
+	var t = (i + j) * G2; 
+	var X0 = i - t; // Unskew the cell origin back to (x,y) space 
+	var Y0 = j - t; 
+	var x0 = xin - X0; // The x,y distances from the cell origin 
+	var y0 = yin - Y0; 
+  // For the 2D case, the simplex shape is an equilateral triangle. 
+  // Determine which simplex we are in. 
+	var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 
+	if (x0 > y0) {i1 = 1; j1 = 0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) 
+	else {i1 = 0; j1 = 1;}      // upper triangle, YX order: (0,0)->(0,1)->(1,1) 
+  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 
+  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 
+  // c = (3-sqrt(3))/6 
+	var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 
+	var y1 = y0 - j1 + G2; 
+	var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords 
+	var y2 = y0 - 1.0 + 2.0 * G2; 
+  // Work out the hashed gradient indices of the three simplex corners 
+	var ii = i & 255; 
+	var jj = j & 255; 
+	var gi0 = this.perm[ii + this.perm[jj]] % 12; 
+	var gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12; 
+	var gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12; 
+  // Calculate the contribution from the three corners 
+	var t0 = 0.5 - x0 * x0 - y0 * y0; 
+	if (t0 < 0) n0 = 0.0; 
+	else { 
+		t0 *= t0; 
+		n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0);  // (x,y) of grad3 used for 2D gradient 
+	} 
+	var t1 = 0.5 - x1 * x1 - y1 * y1; 
+	if (t1 < 0) n1 = 0.0; 
+	else { 
+		t1 *= t1; 
+		n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1); 
+	}
+	var t2 = 0.5 - x2 * x2 - y2 * y2; 
+	if (t2 < 0) n2 = 0.0; 
+	else { 
+		t2 *= t2; 
+		n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2); 
+	} 
+  // Add contributions from each corner to get the final noise value. 
+  // The result is scaled to return values in the interval [-1,1]. 
+	return 70.0 * (n0 + n1 + n2); 
+};
+
+// 3D simplex noise 
+SimplexNoise.prototype.noise3d = function(xin, yin, zin) { 
+	var n0, n1, n2, n3; // Noise contributions from the four corners 
+  // Skew the input space to determine which simplex cell we're in 
+	var F3 = 1.0 / 3.0; 
+	var s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D 
+	var i = Math.floor(xin + s); 
+	var j = Math.floor(yin + s); 
+	var k = Math.floor(zin + s); 
+	var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too 
+	var t = (i + j + k) * G3; 
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z) space 
+	var Y0 = j - t; 
+	var Z0 = k - t; 
+	var x0 = xin - X0; // The x,y,z distances from the cell origin 
+	var y0 = yin - Y0; 
+	var z0 = zin - Z0; 
+  // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 
+  // Determine which simplex we are in. 
+	var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 
+	var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 
+	if (x0 >= y0) { 
+		if (y0 >= z0) 
+      { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order 
+      else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order 
+		else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order 
+	} 
+	else { // x0<y0 
+		if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } // Z Y X order 
+    else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } // Y Z X order 
+		else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // Y X Z order 
+	} 
+  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), 
+  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and 
+  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where 
+  // c = 1/6.
+	var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords 
+	var y1 = y0 - j1 + G3; 
+	var z1 = z0 - k1 + G3; 
+	var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords 
+	var y2 = y0 - j2 + 2.0 * G3; 
+	var z2 = z0 - k2 + 2.0 * G3; 
+	var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords 
+	var y3 = y0 - 1.0 + 3.0 * G3; 
+	var z3 = z0 - 1.0 + 3.0 * G3; 
+  // Work out the hashed gradient indices of the four simplex corners 
+	var ii = i & 255; 
+	var jj = j & 255; 
+	var kk = k & 255; 
+	var gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12; 
+	var gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12; 
+	var gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12; 
+	var gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12; 
+  // Calculate the contribution from the four corners 
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; 
+	if (t0 < 0) n0 = 0.0; 
+	else { 
+		t0 *= t0; 
+		n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0); 
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; 
+	if (t1 < 0) n1 = 0.0; 
+	else { 
+		t1 *= t1; 
+		n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1); 
+	} 
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; 
+	if (t2 < 0) n2 = 0.0; 
+	else { 
+		t2 *= t2; 
+		n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2); 
+	} 
+	var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; 
+	if (t3 < 0) n3 = 0.0; 
+	else { 
+		t3 *= t3; 
+		n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3); 
+	} 
+  // Add contributions from each corner to get the final noise value. 
+  // The result is scaled to stay just inside [-1,1] 
+	return 32.0 * (n0 + n1 + n2 + n3); 
+};
+
+// 4D simplex noise
+SimplexNoise.prototype.noise4d = function( x, y, z, w ) {
+	// For faster and easier lookups
+	var grad4 = this.grad4;
+	var simplex = this.simplex;
+	var perm = this.perm;
+	
+   // The skewing and unskewing factors are hairy again for the 4D case
+	var F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
+	var G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
+	var n0, n1, n2, n3, n4; // Noise contributions from the five corners
+   // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
+	var s = (x + y + z + w) * F4; // Factor for 4D skewing
+	var i = Math.floor(x + s);
+	var j = Math.floor(y + s);
+	var k = Math.floor(z + s);
+	var l = Math.floor(w + s);
+	var t = (i + j + k + l) * G4; // Factor for 4D unskewing
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+	var Y0 = j - t;
+	var Z0 = k - t;
+	var W0 = l - t;
+	var x0 = x - X0;  // The x,y,z,w distances from the cell origin
+	var y0 = y - Y0;
+	var z0 = z - Z0;
+	var w0 = w - W0;
+
+   // For the 4D case, the simplex is a 4D shape I won't even try to describe.
+   // To find out which of the 24 possible simplices we're in, we need to
+   // determine the magnitude ordering of x0, y0, z0 and w0.
+   // The method below is a good way of finding the ordering of x,y,z,w and
+   // then find the correct traversal order for the simplex we’re in.
+   // First, six pair-wise comparisons are performed between each possible pair
+   // of the four coordinates, and the results are used to add up binary bits
+   // for an integer index.
+	var c1 = (x0 > y0) ? 32 : 0;
+	var c2 = (x0 > z0) ? 16 : 0;
+	var c3 = (y0 > z0) ? 8 : 0;
+	var c4 = (x0 > w0) ? 4 : 0;
+	var c5 = (y0 > w0) ? 2 : 0;
+	var c6 = (z0 > w0) ? 1 : 0;
+	var c = c1 + c2 + c3 + c4 + c5 + c6;
+	var i1, j1, k1, l1; // The integer offsets for the second simplex corner
+	var i2, j2, k2, l2; // The integer offsets for the third simplex corner
+	var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
+   // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
+   // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
+   // impossible. Only the 24 indices which have non-zero entries make any sense.
+   // We use a thresholding to set the coordinates in turn from the largest magnitude.
+   // The number 3 in the "simplex" array is at the position of the largest coordinate.
+	i1 = simplex[c][0] >= 3 ? 1 : 0;
+	j1 = simplex[c][1] >= 3 ? 1 : 0;
+	k1 = simplex[c][2] >= 3 ? 1 : 0;
+	l1 = simplex[c][3] >= 3 ? 1 : 0;
+   // The number 2 in the "simplex" array is at the second largest coordinate.
+	i2 = simplex[c][0] >= 2 ? 1 : 0;
+	j2 = simplex[c][1] >= 2 ? 1 : 0;    k2 = simplex[c][2] >= 2 ? 1 : 0;
+	l2 = simplex[c][3] >= 2 ? 1 : 0;
+   // The number 1 in the "simplex" array is at the second smallest coordinate.
+	i3 = simplex[c][0] >= 1 ? 1 : 0;
+	j3 = simplex[c][1] >= 1 ? 1 : 0;
+	k3 = simplex[c][2] >= 1 ? 1 : 0;
+	l3 = simplex[c][3] >= 1 ? 1 : 0;
+   // The fifth corner has all coordinate offsets = 1, so no need to look that up.
+	var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
+	var y1 = y0 - j1 + G4;
+	var z1 = z0 - k1 + G4;
+	var w1 = w0 - l1 + G4;
+	var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
+	var y2 = y0 - j2 + 2.0 * G4;
+	var z2 = z0 - k2 + 2.0 * G4;
+	var w2 = w0 - l2 + 2.0 * G4;
+	var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
+	var y3 = y0 - j3 + 3.0 * G4;
+	var z3 = z0 - k3 + 3.0 * G4;
+	var w3 = w0 - l3 + 3.0 * G4;
+	var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
+	var y4 = y0 - 1.0 + 4.0 * G4;
+	var z4 = z0 - 1.0 + 4.0 * G4;
+	var w4 = w0 - 1.0 + 4.0 * G4;
+   // Work out the hashed gradient indices of the five simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var kk = k & 255;
+	var ll = l & 255;
+	var gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
+	var gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
+	var gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
+	var gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
+	var gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
+   // Calculate the contribution from the five corners
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
+	if (t0 < 0) n0 = 0.0;
+	else {
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
+	if (t1 < 0) n1 = 0.0;
+	else {
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
+	}
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
+	if (t2 < 0) n2 = 0.0;
+	else {
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
+	}   var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
+	if (t3 < 0) n3 = 0.0;
+	else {
+		t3 *= t3;
+		n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
+	}
+	var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
+	if (t4 < 0) n4 = 0.0;
+	else {
+		t4 *= t4;
+		n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
+	}
+   // Sum up and scale the result to cover the range [-1,1]
+	return 27.0 * (n0 + n1 + n2 + n3 + n4);
+};

+ 229 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/SkyShader.js

@@ -0,0 +1,229 @@
+/**
+ * @author zz85 / https://github.com/zz85
+ *
+ * Based on "A Practical Analytic Model for Daylight"
+ * aka The Preetham Model, the de facto standard analytic skydome model
+ * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
+ *
+ * First implemented by Simon Wallner
+ * http://www.simonwallner.at/projects/atmospheric-scattering
+ *
+ * Improved by Martin Upitis
+ * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
+ *
+ * Three.js integration by zz85 http://twitter.com/blurspline
+*/
+
+THREE.ShaderLib[ 'sky' ] = {
+
+	uniforms: {
+
+		luminance: { value: 1 },
+		turbidity: { value: 2 },
+		rayleigh: { value: 1 },
+		mieCoefficient: { value: 0.005 },
+		mieDirectionalG: { value: 0.8 },
+		sunPosition: { value: new THREE.Vector3() }
+
+	},
+
+	vertexShader: [
+
+		"uniform vec3 sunPosition;",
+		"uniform float rayleigh;",
+		"uniform float turbidity;",
+		"uniform float mieCoefficient;",
+
+		"varying vec3 vWorldPosition;",
+		"varying vec3 vSunDirection;",
+		"varying float vSunfade;",
+		"varying vec3 vBetaR;",
+		"varying vec3 vBetaM;",
+		"varying float vSunE;",
+
+		"const vec3 up = vec3(0.0, 1.0, 0.0);",
+
+		// constants for atmospheric scattering
+		"const float e = 2.71828182845904523536028747135266249775724709369995957;",
+		"const float pi = 3.141592653589793238462643383279502884197169;",
+
+		// mie stuff
+		// K coefficient for the primaries
+		"const float v = 4.0;",
+		"const vec3 K = vec3(0.686, 0.678, 0.666);",
+
+		// see http://blenderartists.org/forum/showthread.php?321110-Shaders-and-Skybox-madness
+		// A simplied version of the total Reayleigh scattering to works on browsers that use ANGLE
+		"const vec3 simplifiedRayleigh = 0.0005 / vec3(94, 40, 18);",
+
+		// wavelength of used primaries, according to preetham
+		"const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);",
+
+		// earth shadow hack
+		"const float cutoffAngle = pi/1.95;",
+		"const float steepness = 1.5;",
+		"const float EE = 1000.0;",
+
+		"float sunIntensity(float zenithAngleCos)",
+		"{",
+			"zenithAngleCos = clamp(zenithAngleCos, -1.0, 1.0);",
+			"return EE * max(0.0, 1.0 - pow(e, -((cutoffAngle - acos(zenithAngleCos))/steepness)));",
+		"}",
+
+		"vec3 totalMie(vec3 lambda, float T)",
+		"{",
+			"float c = (0.2 * T ) * 10E-18;",
+			"return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;",
+		"}",
+
+		"void main() {",
+
+			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+			"vWorldPosition = worldPosition.xyz;",
+
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"vSunDirection = normalize(sunPosition);",
+
+			"vSunE = sunIntensity(dot(vSunDirection, up));",
+
+			"vSunfade = 1.0-clamp(1.0-exp((sunPosition.y/450000.0)),0.0,1.0);",
+
+			"float rayleighCoefficient = rayleigh - (1.0 * (1.0-vSunfade));",
+
+			// extinction (absorbtion + out scattering)
+			// rayleigh coefficients
+			"vBetaR = simplifiedRayleigh * rayleighCoefficient;",
+
+			// mie coefficients
+			"vBetaM = totalMie(lambda, turbidity) * mieCoefficient;",
+
+		"}"
+
+	].join( "\n" ),
+
+	fragmentShader: [
+
+		"varying vec3 vWorldPosition;",
+		"varying vec3 vSunDirection;",
+		"varying float vSunfade;",
+		"varying vec3 vBetaR;",
+		"varying vec3 vBetaM;",
+		"varying float vSunE;",
+
+		"uniform float luminance;",
+		"uniform float mieDirectionalG;",
+
+		"const vec3 cameraPos = vec3(0., 0., 0.);",
+
+		// constants for atmospheric scattering
+		"const float pi = 3.141592653589793238462643383279502884197169;",
+
+		"const float n = 1.0003;", // refractive index of air
+		"const float N = 2.545E25;", // number of molecules per unit volume for air at
+									// 288.15K and 1013mb (sea level -45 celsius)
+
+		// optical length at zenith for molecules
+		"const float rayleighZenithLength = 8.4E3;",
+		"const float mieZenithLength = 1.25E3;",
+		"const vec3 up = vec3(0.0, 1.0, 0.0);",
+
+		"const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;",
+		// 66 arc seconds -> degrees, and the cosine of that
+
+		"float rayleighPhase(float cosTheta)",
+		"{",
+			"return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));",
+		"}",
+
+		"float hgPhase(float cosTheta, float g)",
+		"{",
+			"return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));",
+		"}",
+
+		// Filmic ToneMapping http://filmicgames.com/archives/75
+		"const float A = 0.15;",
+		"const float B = 0.50;",
+		"const float C = 0.10;",
+		"const float D = 0.20;",
+		"const float E = 0.02;",
+		"const float F = 0.30;",
+
+		"const float whiteScale = 1.0748724675633854;", // 1.0 / Uncharted2Tonemap(1000.0)
+
+		"vec3 Uncharted2Tonemap(vec3 x)",
+		"{",
+		   "return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;",
+		"}",
+
+
+		"void main() ",
+		"{",
+			// optical length
+			// cutoff angle at 90 to avoid singularity in next formula.
+			"float zenithAngle = acos(max(0.0, dot(up, normalize(vWorldPosition - cameraPos))));",
+			"float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));",
+			"float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));",
+
+			// combined extinction factor
+			"vec3 Fex = exp(-(vBetaR * sR + vBetaM * sM));",
+
+			// in scattering
+			"float cosTheta = dot(normalize(vWorldPosition - cameraPos), vSunDirection);",
+
+			"float rPhase = rayleighPhase(cosTheta*0.5+0.5);",
+			"vec3 betaRTheta = vBetaR * rPhase;",
+
+			"float mPhase = hgPhase(cosTheta, mieDirectionalG);",
+			"vec3 betaMTheta = vBetaM * mPhase;",
+
+			"vec3 Lin = pow(vSunE * ((betaRTheta + betaMTheta) / (vBetaR + vBetaM)) * (1.0 - Fex),vec3(1.5));",
+			"Lin *= mix(vec3(1.0),pow(vSunE * ((betaRTheta + betaMTheta) / (vBetaR + vBetaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up, vSunDirection),5.0),0.0,1.0));",
+
+			//nightsky
+			"vec3 direction = normalize(vWorldPosition - cameraPos);",
+			"float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]",
+			"float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]",
+			"vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);",
+			"vec3 L0 = vec3(0.1) * Fex;",
+
+			// composition + solar disc
+			"float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);",
+			"L0 += (vSunE * 19000.0 * Fex)*sundisk;",
+
+			"vec3 texColor = (Lin+L0) * 0.04 + vec3(0.0, 0.0003, 0.00075);",
+
+			"vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);",
+			"vec3 color = curr*whiteScale;",
+
+			"vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*vSunfade))));",
+
+			"gl_FragColor.rgb = retColor;",
+
+			"gl_FragColor.a = 1.0;",
+		"}"
+
+	].join( "\n" )
+
+};
+
+THREE.Sky = function () {
+
+	var skyShader = THREE.ShaderLib[ "sky" ];
+	var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
+
+	var skyMat = new THREE.ShaderMaterial( {
+		fragmentShader: skyShader.fragmentShader,
+		vertexShader: skyShader.vertexShader,
+		uniforms: skyUniforms,
+		side: THREE.BackSide
+	} );
+
+	var skyGeo = new THREE.SphereBufferGeometry( 450000, 32, 15 );
+	var skyMesh = new THREE.Mesh( skyGeo, skyMat );
+
+	// Expose variables
+	this.mesh = skyMesh;
+	this.uniforms = skyUniforms;
+
+};

+ 280 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/TimelinerController.js

@@ -0,0 +1,280 @@
+/**
+ * Controller class for the Timeliner GUI.
+ *
+ * Timeliner GUI library (required to use this class):
+ *
+ * 		./libs/timeliner_gui.min.js
+ *
+ * Source code:
+ *
+ * 		https://github.com/tschw/timeliner_gui
+ * 		https://github.com/zz85/timeliner (fork's origin)
+ *
+ * @author tschw
+ *
+ */
+
+THREE.TimelinerController = function TimelinerController( scene, trackInfo, onUpdate ) {
+
+	this._scene = scene;
+	this._trackInfo = trackInfo;
+
+	this._onUpdate = onUpdate;
+
+	this._mixer = new THREE.AnimationMixer( scene );
+	this._clip = null;
+	this._action = null;
+
+	this._tracks = {};
+	this._propRefs = {};
+	this._channelNames = [];
+
+};
+
+THREE.TimelinerController.prototype = {
+
+	constructor: THREE.TimelinerController,
+
+	init: function( timeliner ) {
+
+		var tracks = [],
+			trackInfo = this._trackInfo;
+
+		for ( var i = 0, n = trackInfo.length; i !== n; ++ i ) {
+
+			var spec = trackInfo[ i ];
+
+			tracks.push( this._addTrack(
+					spec.type, spec.propertyPath,
+					spec.initialValue, spec.interpolation ) );
+		}
+
+		this._clip = new THREE.AnimationClip( 'editclip', 0, tracks );
+		this._action = this._mixer.clipAction( this._clip ).play();
+
+	},
+
+	setDisplayTime: function( time ) {
+
+		this._action.time = time;
+		this._mixer.update( 0 );
+
+		this._onUpdate();
+
+	},
+
+	setDuration: function( duration ) {
+
+		this._clip.duration = duration;
+
+	},
+
+	getChannelNames: function() {
+
+		return this._channelNames;
+
+	},
+
+	getChannelKeyTimes: function( channelName ) {
+
+		return this._tracks[ channelName ].times;
+
+	},
+
+	setKeyframe: function( channelName, time ) {
+
+		var track = this._tracks[ channelName ],
+			times = track.times,
+			index = Timeliner.binarySearch( times, time ),
+			values = track.values,
+			stride = track.getValueSize(),
+			offset = index * stride;
+
+		if ( index < 0 ) {
+
+			// insert new keyframe
+
+			index = ~ index;
+			offset = index * stride;
+
+			var nTimes = times.length + 1,
+				nValues = values.length + stride;
+
+			for ( var i = nTimes - 1; i !== index; -- i ) {
+
+				times[ i ] = times[ i - 1 ];
+
+			}
+
+			for ( var i = nValues - 1,
+					e = offset + stride - 1; i !== e; -- i ) {
+
+				values[ i ] = values[ i - stride ];
+
+			}
+
+		}
+
+		times[ index ] = time;
+		this._propRefs[ channelName ].getValue( values, offset );
+
+	},
+
+	delKeyframe: function( channelName, time ) {
+
+		var track = this._tracks[ channelName ],
+			times = track.times,
+			index = Timeliner.binarySearch( times, time );
+
+		// we disallow to remove the keyframe when it is the last one we have,
+		// since the animation system is designed to always produce a defined
+		// state
+
+		if ( times.length > 1 && index >= 0 ) {
+
+			var nTimes = times.length - 1,
+				values = track.values,
+				stride = track.getValueSize(),
+				nValues = values.length - stride;
+
+			// note: no track.getValueSize when array sizes are out of sync
+
+			for ( var i = index; i !== nTimes; ++ i ) {
+
+				times[ i ] = times[ i + 1 ];
+
+			}
+
+			times.pop();
+
+			for ( var offset = index * stride; offset !== nValues; ++ offset ) {
+
+				values[ offset ] = values[ offset + stride ];
+
+			}
+
+			values.length = nValues;
+
+		}
+
+	},
+
+	moveKeyframe: function( channelName, time, delta, moveRemaining ) {
+
+		var track = this._tracks[ channelName ],
+			times = track.times,
+			index = Timeliner.binarySearch( times, time );
+
+		if ( index >= 0 ) {
+
+			var endAt = moveRemaining ? times.length : index + 1,
+				needsSort = times[ index - 1 ] <= time ||
+					! moveRemaining && time >= times[ index + 1 ];
+
+			while ( index !== endAt ) times[ index ++ ] += delta;
+
+			if ( needsSort ) this._sort( track );
+
+		}
+
+	},
+
+	serialize: function() {
+
+		var result = {
+				duration: this._clip.duration,
+				channels: {}
+			},
+
+			names = this._channelNames,
+			tracks = this._tracks,
+
+			channels = result.channels;
+
+		for ( var i = 0, n = names.length; i !== n; ++ i ) {
+
+			var name = names[ i ],
+				track = tracks[ name ];
+
+			channels[ name ] = {
+
+				times: track.times,
+				values: track.values
+
+			};
+
+		}
+
+		return result;
+
+	},
+
+	deserialize: function( structs ) {
+
+		var names = this._channelNames,
+			tracks = this._tracks,
+
+			channels = structs.channels;
+
+		this.setDuration( structs.duration );
+
+		for ( var i = 0, n = names.length; i !== n; ++ i ) {
+
+			var name = names[ i ],
+				track = tracks[ name ];
+				data = channels[ name ];
+
+			this._setArray( track.times, data.times );
+			this._setArray( track.values, data.values );
+
+		}
+
+		// update display
+		this.setDisplayTime( this._mixer.time );
+
+	},
+
+	_sort: function( track ) {
+
+		var times = track.times,
+			order = THREE.AnimationUtils.getKeyframeOrder( times );
+
+		this._setArray( times,
+				THREE.AnimationUtils.sortedArray( times, 1, order ) );
+
+		var values = track.values,
+			stride = track.getValueSize();
+
+		this._setArray( values,
+				THREE.AnimationUtils.sortedArray( values, stride, order ) );
+
+	},
+
+	_setArray: function( dst, src ) {
+
+		dst.length = 0;
+		dst.push.apply( dst, src );
+
+	},
+
+	_addTrack: function( type, prop, initialValue, interpolation ) {
+
+		var track = new type(
+				prop, [ 0 ], initialValue, interpolation );
+
+		// data must be in JS arrays so it can be resized
+		track.times = Array.prototype.slice.call( track.times );
+		track.values = Array.prototype.slice.call( track.values );
+
+		this._channelNames.push( prop );
+		this._tracks[ prop ] = track;
+
+		// for recording the state:
+		this._propRefs[ prop ] =
+				new THREE.PropertyBinding( this._scene, prop );
+
+		return track;
+
+	}
+
+};

+ 602 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/TypedArrayUtils.js

@@ -0,0 +1,602 @@
+
+THREE.TypedArrayUtils = {};
+
+/**
+ * In-place quicksort for typed arrays (e.g. for Float32Array)
+ * provides fast sorting
+ * useful e.g. for a custom shader and/or BufferGeometry
+ *
+ * @author Roman Bolzern <roman.bolzern@fhnw.ch>, 2013
+ * @author I4DS http://www.fhnw.ch/i4ds, 2013
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
+ *
+ * Complexity: http://bigocheatsheet.com/ see Quicksort
+ *
+ * Example: 
+ * points: [x, y, z, x, y, z, x, y, z, ...]
+ * eleSize: 3 //because of (x, y, z)
+ * orderElement: 0 //order according to x
+ */
+
+THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
+
+	var stack = [];
+	var sp = - 1;
+	var left = 0;
+	var right = arr.length / eleSize - 1;
+	var tmp = 0.0, x = 0, y = 0;
+
+	var swapF = function ( a, b ) {
+
+		a *= eleSize; b *= eleSize;
+
+		for ( y = 0; y < eleSize; y ++ ) {
+
+			tmp = arr[ a + y ];
+			arr[ a + y ] = arr[ b + y ];
+			arr[ b + y ] = tmp;
+
+		}
+
+	};
+	
+	var i, j, swap = new Float32Array( eleSize ), temp = new Float32Array( eleSize );
+
+	while ( true ) {
+
+		if ( right - left <= 25 ) {
+
+			for ( j = left + 1; j <= right; j ++ ) {
+
+				for ( x = 0; x < eleSize; x ++ ) {
+			
+					swap[ x ] = arr[ j * eleSize + x ];
+
+				}
+				
+				i = j - 1;
+				
+				while ( i >= left && arr[ i * eleSize + orderElement ] > swap[ orderElement ] ) {
+
+					for ( x = 0; x < eleSize; x ++ ) {
+
+						arr[ ( i + 1 ) * eleSize + x ] = arr[ i * eleSize + x ];
+
+					}
+
+					i --;
+
+				}
+
+				for ( x = 0; x < eleSize; x ++ ) {
+
+					arr[ ( i + 1 ) * eleSize + x ] = swap[ x ];
+
+				}
+
+			}
+			
+			if ( sp == - 1 ) break;
+
+			right = stack[ sp -- ]; //?
+			left = stack[ sp -- ];
+
+		} else {
+
+			var median = ( left + right ) >> 1;
+
+			i = left + 1;
+			j = right;
+	
+			swapF( median, i );
+
+			if ( arr[ left * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
+		
+				swapF( left, right );
+				
+			}
+
+			if ( arr[ i * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
+		
+				swapF( i, right );
+		
+			}
+
+			if ( arr[ left * eleSize + orderElement ] > arr[ i * eleSize + orderElement ] ) {
+		
+				swapF( left, i );
+			
+			}
+
+			for ( x = 0; x < eleSize; x ++ ) {
+
+				temp[ x ] = arr[ i * eleSize + x ];
+
+			}
+			
+			while ( true ) {
+				
+				do i ++; while ( arr[ i * eleSize + orderElement ] < temp[ orderElement ] );
+				do j --; while ( arr[ j * eleSize + orderElement ] > temp[ orderElement ] );
+				
+				if ( j < i ) break;
+		
+				swapF( i, j );
+			
+			}
+
+			for ( x = 0; x < eleSize; x ++ ) {
+
+				arr[ ( left + 1 ) * eleSize + x ] = arr[ j * eleSize + x ];
+				arr[ j * eleSize + x ] = temp[ x ];
+
+			}
+
+			if ( right - i + 1 >= j - left ) {
+
+				stack[ ++ sp ] = i;
+				stack[ ++ sp ] = right;
+				right = j - 1;
+
+			} else {
+
+				stack[ ++ sp ] = left;
+				stack[ ++ sp ] = j - 1;
+				left = i;
+
+			}
+
+		}
+
+	}
+
+	return arr;
+
+};
+
+
+
+/**
+ * k-d Tree for typed arrays (e.g. for Float32Array), in-place
+ * provides fast nearest neighbour search
+ * useful e.g. for a custom shader and/or BufferGeometry, saves tons of memory
+ * has no insert and remove, only buildup and neares neighbour search
+ *
+ * Based on https://github.com/ubilabs/kd-tree-javascript by Ubilabs
+ *
+ * @author Roman Bolzern <roman.bolzern@fhnw.ch>, 2013
+ * @author I4DS http://www.fhnw.ch/i4ds, 2013
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
+ *
+ * Requires typed array quicksort
+ *
+ * Example: 
+ * points: [x, y, z, x, y, z, x, y, z, ...]
+ * metric: function(a, b){	return Math.pow(a[0] - b[0], 2) +  Math.pow(a[1] - b[1], 2) +  Math.pow(a[2] - b[2], 2); }  //Manhatten distance
+ * eleSize: 3 //because of (x, y, z)
+ *
+ * Further information (including mathematical properties)
+ * http://en.wikipedia.org/wiki/Binary_tree
+ * http://en.wikipedia.org/wiki/K-d_tree
+ *
+ * If you want to further minimize memory usage, remove Node.depth and replace in search algorithm with a traversal to root node (see comments at THREE.TypedArrayUtils.Kdtree.prototype.Node)
+ */
+
+ THREE.TypedArrayUtils.Kdtree = function ( points, metric, eleSize ) {
+
+	var self = this;
+	
+	var maxDepth = 0;
+	
+	var getPointSet = function ( points, pos ) {
+
+		return points.subarray( pos * eleSize, pos * eleSize + eleSize );
+
+	};
+		
+	function buildTree( points, depth, parent, pos ) {
+
+		var dim = depth % eleSize,
+			median,
+			node,
+			plength = points.length / eleSize;
+
+		if ( depth > maxDepth ) maxDepth = depth;
+		
+		if ( plength === 0 ) return null;
+		if ( plength === 1 ) {
+
+			return new self.Node( getPointSet( points, 0 ), depth, parent, pos );
+
+		}
+
+		THREE.TypedArrayUtils.quicksortIP( points, eleSize, dim );
+		
+		median = Math.floor( plength / 2 );
+		
+		node = new self.Node( getPointSet( points, median ), depth, parent, median + pos );
+		node.left = buildTree( points.subarray( 0, median * eleSize ), depth + 1, node, pos );
+		node.right = buildTree( points.subarray( ( median + 1 ) * eleSize, points.length ), depth + 1, node, pos + median + 1 );
+
+		return node;
+	
+	}
+
+	this.root = buildTree( points, 0, null, 0 );
+		
+	this.getMaxDepth = function () {
+
+		return maxDepth;
+
+	};
+	
+	this.nearest = function ( point, maxNodes, maxDistance ) {
+	
+		 /* point: array of size eleSize 
+			maxNodes: max amount of nodes to return 
+			maxDistance: maximum distance to point result nodes should have
+			condition (not implemented): function to test node before it's added to the result list, e.g. test for view frustum
+		*/
+
+		var i,
+			result,
+			bestNodes;
+
+		bestNodes = new THREE.TypedArrayUtils.Kdtree.BinaryHeap(
+
+			function ( e ) {
+
+				return - e[ 1 ];
+
+			}
+
+					);
+
+		function nearestSearch( node ) {
+
+			var bestChild,
+				dimension = node.depth % eleSize,
+				ownDistance = metric( point, node.obj ),
+				linearDistance = 0,
+				otherChild,
+				i,
+				linearPoint = [];
+
+			function saveNode( node, distance ) {
+
+				bestNodes.push( [ node, distance ] );
+
+				if ( bestNodes.size() > maxNodes ) {
+
+					bestNodes.pop();
+
+				}
+
+			}
+
+			for ( i = 0; i < eleSize; i += 1 ) {
+
+				if ( i === node.depth % eleSize ) {
+
+					linearPoint[ i ] = point[ i ];
+
+				} else {
+
+					linearPoint[ i ] = node.obj[ i ];
+
+				}
+
+			}
+
+			linearDistance = metric( linearPoint, node.obj );
+
+			// if it's a leaf
+
+			if ( node.right === null && node.left === null ) {
+
+				if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
+
+					saveNode( node, ownDistance );
+
+				}
+
+				return;
+
+			}
+
+			if ( node.right === null ) {
+
+				bestChild = node.left;
+
+			} else if ( node.left === null ) {
+
+				bestChild = node.right;
+
+			} else {
+
+				if ( point[ dimension ] < node.obj[ dimension ] ) {
+
+					bestChild = node.left;
+
+				} else {
+
+					bestChild = node.right;
+
+				}
+
+			}
+
+			// recursive search
+
+			nearestSearch( bestChild );
+
+			if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
+
+				saveNode( node, ownDistance );
+
+			}
+
+			// if there's still room or the current distance is nearer than the best distance
+
+			if ( bestNodes.size() < maxNodes || Math.abs( linearDistance ) < bestNodes.peek()[ 1 ] ) {
+
+				if ( bestChild === node.left ) {
+
+					otherChild = node.right;
+
+				} else {
+
+					otherChild = node.left;
+
+				}
+
+				if ( otherChild !== null ) {
+
+					nearestSearch( otherChild );
+
+				}
+
+			}
+
+		}
+
+		if ( maxDistance ) {
+
+			for ( i = 0; i < maxNodes; i += 1 ) {
+
+				bestNodes.push( [ null, maxDistance ] );
+
+			}
+
+		}
+
+		nearestSearch( self.root );
+
+		result = [];
+
+		for ( i = 0; i < maxNodes; i += 1 ) {
+
+			if ( bestNodes.content[ i ][ 0 ] ) {
+
+				result.push( [ bestNodes.content[ i ][ 0 ], bestNodes.content[ i ][ 1 ] ] );
+
+			}
+
+		}
+		
+		return result;
+	
+	};
+	
+};
+
+/**
+ * If you need to free up additional memory and agree with an additional O( log n ) traversal time you can get rid of "depth" and "pos" in Node:
+ * Depth can be easily done by adding 1 for every parent (care: root node has depth 0, not 1)
+ * Pos is a bit tricky: Assuming the tree is balanced (which is the case when after we built it up), perform the following steps:
+ *   By traversing to the root store the path e.g. in a bit pattern (01001011, 0 is left, 1 is right)
+ *   From buildTree we know that "median = Math.floor( plength / 2 );", therefore for each bit...
+ *     0: amountOfNodesRelevantForUs = Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *     1: amountOfNodesRelevantForUs = Math.ceil( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *        pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *     when recursion done, we still need to add all left children of target node:
+ *        pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *        and I think you need to +1 for the current position, not sure.. depends, try it out ^^
+ *
+ * I experienced that for 200'000 nodes you can get rid of 4 MB memory each, leading to 8 MB memory saved.
+ */
+THREE.TypedArrayUtils.Kdtree.prototype.Node = function ( obj, depth, parent, pos ) {
+
+	this.obj = obj;
+	this.left = null;
+	this.right = null;
+	this.parent = parent;
+	this.depth = depth;
+	this.pos = pos;
+
+}; 
+
+/**
+ * Binary heap implementation
+ * @author http://eloquentjavascript.net/appendix2.htm
+ */
+
+THREE.TypedArrayUtils.Kdtree.BinaryHeap = function ( scoreFunction ) {
+
+	this.content = [];
+	this.scoreFunction = scoreFunction;
+
+};
+
+THREE.TypedArrayUtils.Kdtree.BinaryHeap.prototype = {
+
+	push: function ( element ) {
+
+		// Add the new element to the end of the array.
+		this.content.push( element );
+
+		// Allow it to bubble up.
+		this.bubbleUp( this.content.length - 1 );
+
+	},
+
+	pop: function () {
+
+		// Store the first element so we can return it later.
+		var result = this.content[ 0 ];
+
+		// Get the element at the end of the array.
+		var end = this.content.pop();
+
+		// If there are any elements left, put the end element at the
+		// start, and let it sink down.
+		if ( this.content.length > 0 ) {
+
+			this.content[ 0 ] = end;
+			this.sinkDown( 0 );
+
+		}
+
+		return result;
+
+	},
+
+	peek: function () {
+
+		return this.content[ 0 ];
+
+	},
+
+	remove: function ( node ) {
+
+		var len = this.content.length;
+
+		// To remove a value, we must search through the array to find it.
+		for ( var i = 0; i < len; i ++ ) {
+
+			if ( this.content[ i ] == node ) {
+
+				// When it is found, the process seen in 'pop' is repeated
+				// to fill up the hole.
+				var end = this.content.pop();
+
+				if ( i != len - 1 ) {
+
+					this.content[ i ] = end;
+
+					if ( this.scoreFunction( end ) < this.scoreFunction( node ) ) {
+
+						this.bubbleUp( i );
+
+					} else {
+
+						this.sinkDown( i );
+
+					}
+
+				}
+
+				return;
+
+			}
+
+		}
+
+		throw new Error( "Node not found." );
+
+	},
+
+	size: function () {
+
+		return this.content.length;
+
+	},
+
+	bubbleUp: function ( n ) {
+
+		// Fetch the element that has to be moved.
+		var element = this.content[ n ];
+
+		// When at 0, an element can not go up any further.
+		while ( n > 0 ) {
+
+			// Compute the parent element's index, and fetch it.
+			var parentN = Math.floor( ( n + 1 ) / 2 ) - 1,
+				parent = this.content[ parentN ];
+
+			// Swap the elements if the parent is greater.
+			if ( this.scoreFunction( element ) < this.scoreFunction( parent ) ) {
+
+				this.content[ parentN ] = element;
+				this.content[ n ] = parent;
+
+				// Update 'n' to continue at the new position.
+				n = parentN;
+
+			} else {
+
+				// Found a parent that is less, no need to move it further.
+				break;
+
+			}
+
+		}
+
+	},
+
+	sinkDown: function ( n ) {
+
+		// Look up the target element and its score.
+		var length = this.content.length,
+			element = this.content[ n ],
+			elemScore = this.scoreFunction( element );
+
+		while ( true ) {
+
+			// Compute the indices of the child elements.
+			var child2N = ( n + 1 ) * 2, child1N = child2N - 1;
+
+			// This is used to store the new position of the element, if any.
+			var swap = null;
+
+			// If the first child exists (is inside the array)...
+			if ( child1N < length ) {
+
+				// Look it up and compute its score.
+				var child1 = this.content[ child1N ],
+					child1Score = this.scoreFunction( child1 );
+
+				// If the score is less than our element's, we need to swap.
+				if ( child1Score < elemScore ) swap = child1N;
+
+			}
+
+			// Do the same checks for the other child.
+			if ( child2N < length ) {
+
+				var child2 = this.content[ child2N ],
+					child2Score = this.scoreFunction( child2 );
+
+				if ( child2Score < ( swap === null ? elemScore : child1Score ) ) swap = child2N;
+
+			}
+
+			// If the element needs to be moved, swap it, and continue.
+			if ( swap !== null ) {
+
+				this.content[ n ] = this.content[ swap ];
+				this.content[ swap ] = element;
+				n = swap;
+
+			} else {
+
+				// Otherwise, we are done.
+				break;
+
+			}
+
+		}
+
+	}
+
+};

+ 141 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/UCSCharacter.js

@@ -0,0 +1,141 @@
+THREE.UCSCharacter = function() {
+
+	var scope = this;
+
+	var mesh;
+
+	this.scale = 1;
+
+	this.root = new THREE.Object3D();
+
+	this.numSkins = undefined;
+	this.numMorphs = undefined;
+
+	this.skins = [];
+	this.materials = [];
+	this.morphs = [];
+
+	this.mixer = new THREE.AnimationMixer( this.root );
+
+	this.onLoadComplete = function () {};
+
+	this.loadCounter = 0;
+
+	this.loadParts = function ( config ) {
+
+		this.numSkins = config.skins.length;
+		this.numMorphs = config.morphs.length;
+
+		// Character geometry + number of skins
+		this.loadCounter = 1 + config.skins.length;
+
+		// SKINS
+		this.skins = loadTextures( config.baseUrl + "skins/", config.skins );
+		this.materials = createMaterials( this.skins );
+
+		// MORPHS
+		this.morphs = config.morphs;
+
+		// CHARACTER
+		var loader = new THREE.JSONLoader();
+		console.log( config.baseUrl + config.character );
+		loader.load( config.baseUrl + config.character, function( geometry ) {
+
+			geometry.computeBoundingBox();
+			geometry.computeVertexNormals();
+
+			mesh = new THREE.SkinnedMesh( geometry, new THREE.MultiMaterial() );
+			mesh.name = config.character;
+			scope.root.add( mesh );
+
+			var bb = geometry.boundingBox;
+			scope.root.scale.set( config.s, config.s, config.s );
+			scope.root.position.set( config.x, config.y - bb.min.y * config.s, config.z );
+
+			mesh.castShadow = true;
+			mesh.receiveShadow = true;
+
+			scope.mixer.clipAction( geometry.animations[0], mesh ).play();
+
+			scope.setSkin( 0 );
+
+			scope.checkLoadComplete();
+
+		} );
+
+	};
+
+	this.setSkin = function( index ) {
+
+		if ( mesh && scope.materials ) {
+
+			mesh.material = scope.materials[ index ];
+
+		}
+
+	};
+
+	this.updateMorphs = function( influences ) {
+
+		if ( mesh ) {
+
+			for ( var i = 0; i < scope.numMorphs; i ++ ) {
+
+				mesh.morphTargetInfluences[ i ] = influences[ scope.morphs[ i ] ] / 100;
+
+			}
+
+		}
+
+	};
+
+	function loadTextures( baseUrl, textureUrls ) {
+
+		var textureLoader = new THREE.TextureLoader();
+		var textures = [];
+
+		for ( var i = 0; i < textureUrls.length; i ++ ) {
+
+			textures[ i ] = textureLoader.load( baseUrl + textureUrls[ i ], scope.checkLoadComplete );
+			textures[ i ].mapping = THREE.UVMapping;
+			textures[ i ].name = textureUrls[ i ];
+
+		}
+
+		return textures;
+
+	}
+
+	function createMaterials( skins ) {
+
+		var materials = [];
+
+		for ( var i = 0; i < skins.length; i ++ ) {
+
+			materials[ i ] = new THREE.MeshLambertMaterial( {
+				color: 0xeeeeee,
+				specular: 10.0,
+				map: skins[ i ],
+				skinning: true,
+				morphTargets: true
+			} );
+
+		}
+
+		return materials;
+
+	}
+
+	this.checkLoadComplete = function () {
+
+		scope.loadCounter -= 1;
+
+		if ( scope.loadCounter === 0 ) {
+
+			scope.onLoadComplete();
+
+		}
+
+	}
+
+};

+ 447 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/Volume.js

@@ -0,0 +1,447 @@
+/**
+ * This class had been written to handle the output of the NRRD loader.
+ * It contains a volume of data and informations about it.
+ * For now it only handles 3 dimensional data.
+ * See the webgl_loader_nrrd.html example and the loaderNRRD.js file to see how to use this class.
+ * @class
+ * @author Valentin Demeusy / https://github.com/stity
+ * @param   {number}        xLength         Width of the volume
+ * @param   {number}        yLength         Length of the volume
+ * @param   {number}        zLength         Depth of the volume
+ * @param   {string}        type            The type of data (uint8, uint16, ...)
+ * @param   {ArrayBuffer}   arrayBuffer     The buffer with volume data
+ */
+THREE.Volume = function( xLength, yLength, zLength, type, arrayBuffer ) {
+
+	if ( arguments.length > 0 ) {
+
+		/**
+		 * @member {number} xLength Width of the volume in the IJK coordinate system
+		 */
+		this.xLength = Number( xLength ) || 1;
+		/**
+		 * @member {number} yLength Height of the volume in the IJK coordinate system
+		 */
+		this.yLength = Number( yLength ) || 1;
+		/**
+		 * @member {number} zLength Depth of the volume in the IJK coordinate system
+		 */
+		this.zLength = Number( zLength ) || 1;
+
+		/**
+		 * @member {TypedArray} data Data of the volume
+		 */
+
+		switch ( type ) {
+
+			case 'Uint8' :
+			case 'uint8' :
+			case 'uchar' :
+			case 'unsigned char' :
+			case 'uint8_t' :
+				this.data = new Uint8Array( arrayBuffer );
+				break;
+			case 'Int8' :
+			case 'int8' :
+			case 'signed char' :
+			case 'int8_t' :
+				this.data = new Int8Array( arrayBuffer );
+				break;
+			case 'Int16' :
+			case 'int16' :
+			case 'short' :
+			case 'short int' :
+			case 'signed short' :
+			case 'signed short int' :
+			case 'int16_t' :
+				this.data = new Int16Array( arrayBuffer );
+				break;
+			case 'Uint16' :
+			case 'uint16' :
+			case 'ushort' :
+			case 'unsigned short' :
+			case 'unsigned short int' :
+			case 'uint16_t' :
+				this.data = new Uint16Array( arrayBuffer );
+				break;
+			case 'Int32' :
+			case 'int32' :
+			case 'int' :
+			case 'signed int' :
+			case 'int32_t' :
+				this.data = new Int32Array( arrayBuffer );
+				break;
+			case 'Uint32' :
+			case 'uint32' :
+			case 'uint' :
+			case 'unsigned int' :
+			case 'uint32_t' :
+				this.data = new Uint32Array( arrayBuffer );
+				break;
+			case 'longlong' :
+			case 'long long' :
+			case 'long long int' :
+			case 'signed long long' :
+			case 'signed long long int' :
+			case 'int64' :
+			case 'int64_t' :
+			case 'ulonglong' :
+			case 'unsigned long long' :
+			case 'unsigned long long int' :
+			case 'uint64' :
+			case 'uint64_t' :
+				throw 'Error in THREE.Volume constructor : this type is not supported in JavaScript';
+				break;
+			case 'Float32' :
+			case 'float32' :
+			case 'float' :
+				this.data = new Float32Array( arrayBuffer );
+				break;
+			case 'Float64' :
+			case 'float64' :
+			case 'double' :
+				this.data = new Float64Array( arrayBuffer );
+				break;
+			default :
+				this.data = new Uint8Array( arrayBuffer );
+
+		}
+
+		if ( this.data.length !== this.xLength * this.yLength * this.zLength ) {
+
+			throw 'Error in THREE.Volume constructor, lengths are not matching arrayBuffer size';
+
+		}
+
+	}
+
+	/**
+	 * @member {Array}  spacing Spacing to apply to the volume from IJK to RAS coordinate system
+	 */
+	this.spacing = [ 1, 1, 1 ];
+	/**
+	 * @member {Array}  offset Offset of the volume in the RAS coordinate system
+	 */
+	this.offset = [ 0, 0, 0 ];
+	/**
+	 * @member {THREE.Martrix3} matrix The IJK to RAS matrix
+	 */
+	this.matrix = new THREE.Matrix3();
+	this.matrix.identity();
+	/**
+	 * @member {THREE.Martrix3} inverseMatrix The RAS to IJK matrix
+	 */
+	/**
+	 * @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
+	 *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
+	 */
+	var lowerThreshold = - Infinity;
+	Object.defineProperty( this, 'lowerThreshold', {
+		get : function() {
+
+			return lowerThreshold;
+
+		},
+		set : function( value ) {
+
+			lowerThreshold = value;
+			this.sliceList.forEach( function( slice ) {
+
+				slice.geometryNeedsUpdate = true
+
+			} );
+
+		}
+	} );
+	/**
+	 * @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
+	 *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
+	 */
+	var upperThreshold = Infinity;
+	Object.defineProperty( this, 'upperThreshold', {
+		get : function() {
+
+			return upperThreshold;
+
+		},
+		set : function( value ) {
+
+			upperThreshold = value;
+			this.sliceList.forEach( function( slice ) {
+
+				slice.geometryNeedsUpdate = true;
+
+			} );
+
+		}
+	} );
+
+
+	/**
+	 * @member {Array} sliceList The list of all the slices associated to this volume
+	 */
+	this.sliceList = [];
+
+
+	/**
+	 * @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
+	 */
+
+};
+
+THREE.Volume.prototype = {
+
+	constructor : THREE.Volume,
+
+	/**
+	 * @member {Function} getData Shortcut for data[access(i,j,k)]
+	 * @memberof THREE.Volume
+	 * @param {number} i    First coordinate
+	 * @param {number} j    Second coordinate
+	 * @param {number} k    Third coordinate
+	 * @returns {number}  value in the data array
+	 */
+	getData : function( i, j, k ) {
+
+		return this.data[ k * this.xLength * this.yLength + j * this.xLength + i ];
+
+	},
+
+	/**
+	 * @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system
+	 * @memberof THREE.Volume
+	 * @param {number} i    First coordinate
+	 * @param {number} j    Second coordinate
+	 * @param {number} k    Third coordinate
+	 * @returns {number}  index
+	 */
+	access : function( i, j, k ) {
+
+		return k * this.xLength * this.yLength + j * this.xLength + i;
+
+	},
+
+	/**
+	 * @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
+	 * @memberof THREE.Volume
+	 * @param {number} index index of the voxel
+	 * @returns {Array}  [x,y,z]
+	 */
+	reverseAccess : function( index ) {
+
+		var z = Math.floor( index / ( this.yLength * this.xLength ) );
+		var y = Math.floor( ( index - z * this.yLength * this.xLength ) / this.xLength );
+		var x = index - z * this.yLength * this.xLength - y * this.xLength;
+		return [ x, y, z ];
+
+	},
+
+	/**
+	 * @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced
+	 * @memberof THREE.Volume
+	 * @param {Function} functionToMap A function to apply to every voxel, will be called with the following parameters :
+	 *                                 value of the voxel
+	 *                                 index of the voxel
+	 *                                 the data (TypedArray)
+	 * @param {Object}   context    You can specify a context in which call the function, default if this Volume
+	 * @returns {THREE.Volume}   this
+	 */
+	map : function( functionToMap, context ) {
+
+		var length = this.data.length;
+		context = context || this;
+
+		for ( var i = 0; i < length; i ++ ) {
+
+			this.data[ i ] = functionToMap.call( context, this.data[ i ], i, this.data );
+
+		}
+
+		return this;
+
+	},
+
+	/**
+	 * @member {Function} extractPerpendicularPlane Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
+	 * @memberof THREE.Volume
+	 * @param {string}            axis  the normal axis to the slice 'x' 'y' or 'z'
+	 * @param {number}            index the index of the slice
+	 * @returns {Object} an object containing all the usefull information on the geometry of the slice
+	 */
+	extractPerpendicularPlane : function( axis, RASIndex ) {
+
+		var iLength,
+		jLength,
+		sliceAccess,
+		planeMatrix = ( new THREE.Matrix4() ).identity(),
+		volume = this,
+		planeWidth,
+		planeHeight,
+		firstSpacing,
+		secondSpacing,
+		positionOffset,
+		IJKIndex;
+
+		var axisInIJK = new THREE.Vector3(),
+		firstDirection = new THREE.Vector3(),
+		secondDirection = new THREE.Vector3();
+
+		var dimensions = new THREE.Vector3( this.xLength, this.yLength, this.zLength );
+
+
+		switch ( axis ) {
+
+			case 'x' :
+				axisInIJK.set( 1, 0, 0 );
+				firstDirection.set( 0, 0, - 1 );
+				secondDirection.set( 0, - 1, 0 );
+				firstSpacing = this.spacing[ 2 ];
+				secondSpacing = this.spacing[ 1 ];
+				IJKIndex = new THREE.Vector3( RASIndex, 0, 0 );
+
+				planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationY( Math.PI / 2 ) );
+				positionOffset = ( volume.RASDimensions[ 0 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( RASIndex - positionOffset, 0, 0 ) );
+				break;
+			case 'y' :
+				axisInIJK.set( 0, 1, 0 );
+				firstDirection.set( 1, 0, 0 );
+				secondDirection.set( 0, 0, 1 );
+				firstSpacing = this.spacing[ 0 ];
+				secondSpacing = this.spacing[ 2 ];
+				IJKIndex = new THREE.Vector3( 0, RASIndex, 0 );
+
+				planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationX( - Math.PI / 2 ) );
+				positionOffset = ( volume.RASDimensions[ 1 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( 0, RASIndex - positionOffset, 0 ) );
+				break;
+			case 'z' :
+			default :
+				axisInIJK.set( 0, 0, 1 );
+				firstDirection.set( 1, 0, 0 );
+				secondDirection.set( 0, - 1, 0 );
+				firstSpacing = this.spacing[ 0 ];
+				secondSpacing = this.spacing[ 1 ];
+				IJKIndex = new THREE.Vector3( 0, 0, RASIndex );
+
+				positionOffset = ( volume.RASDimensions[ 2 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( 0, 0, RASIndex - positionOffset ) );
+				break;
+		}
+
+		firstDirection.applyMatrix4( volume.inverseMatrix ).normalize();
+		firstDirection.argVar = 'i';
+		secondDirection.applyMatrix4( volume.inverseMatrix ).normalize();
+		secondDirection.argVar = 'j';
+		axisInIJK.applyMatrix4( volume.inverseMatrix ).normalize();
+		iLength = Math.floor( Math.abs( firstDirection.dot( dimensions ) ) );
+		jLength = Math.floor( Math.abs( secondDirection.dot( dimensions ) ) );
+		planeWidth = Math.abs( iLength * firstSpacing );
+		planeHeight = Math.abs( jLength * secondSpacing );
+
+		IJKIndex = Math.abs( Math.round( IJKIndex.applyMatrix4( volume.inverseMatrix ).dot( axisInIJK ) ) );
+		var base = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ];
+		var iDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 0 ] ) ) > 0.9;
+
+		} );
+		var jDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 1 ] ) ) > 0.9;
+
+		} );
+		var kDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 2 ] ) ) > 0.9;
+
+		} );
+		var argumentsWithInversion = [ 'volume.xLength-1-', 'volume.yLength-1-', 'volume.zLength-1-' ];
+		var arguments = [ 'i', 'j', 'k' ];
+		var argArray = [ iDirection, jDirection, kDirection ].map( function( direction, n ) {
+
+			return ( direction.dot( base[ n ] ) > 0 ? '' : argumentsWithInversion[ n ] ) + ( direction === axisInIJK ? 'IJKIndex' : direction.argVar )
+
+		} );
+		var argString = argArray.join( ',' );
+		sliceAccess = eval( '(function sliceAccess (i,j) {return volume.access( ' + argString + ');})' );
+
+
+		return {
+			iLength : iLength,
+			jLength : jLength,
+			sliceAccess : sliceAccess,
+			matrix : planeMatrix,
+			planeWidth : planeWidth,
+			planeHeight : planeHeight
+		}
+
+	},
+
+	/**
+	 * @member {Function} extractSlice Returns a slice corresponding to the given axis and index
+	 *                        The coordinate are given in the Right Anterior Superior coordinate format
+	 * @memberof THREE.Volume
+	 * @param {string}            axis  the normal axis to the slice 'x' 'y' or 'z'
+	 * @param {number}            index the index of the slice
+	 * @returns {THREE.VolumeSlice} the extracted slice
+	 */
+	extractSlice : function( axis, index ) {
+
+		var slice = new THREE.VolumeSlice( this, index, axis );
+		this.sliceList.push( slice );
+		return slice;
+
+	},
+
+	/**
+	 * @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume
+	 * @see THREE.VolumeSlice.repaint
+	 * @memberof THREE.Volume
+	 * @returns {THREE.Volume} this
+	 */
+	repaintAllSlices : function() {
+
+		this.sliceList.forEach( function( slice ) {
+
+			slice.repaint();
+
+		} );
+
+		return this;
+
+	},
+
+	/**
+	 * @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume
+	 * @memberof THREE.Volume
+	 * @returns {Array} [min,max]
+	 */
+	computeMinMax : function() {
+
+		var min = Infinity;
+		var max = - Infinity;
+
+		// buffer the length
+		var datasize = this.data.length;
+
+		var i = 0;
+		for ( i = 0; i < datasize; i ++ ) {
+
+			if ( ! isNaN( this.data[ i ] ) ) {
+
+				var value = this.data[ i ];
+				min = Math.min( min, value );
+				max = Math.max( max, value );
+
+			}
+
+		}
+		this.min = min;
+		this.max = max;
+
+		return [ min, max ];
+
+	}
+
+};

+ 217 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/VolumeSlice.js

@@ -0,0 +1,217 @@
+/**
+ * This class has been made to hold a slice of a volume data
+ * @class
+ * @author Valentin Demeusy / https://github.com/stity
+ * @param   {THREE.Volume} volume    The associated volume
+ * @param   {number}       [index=0] The index of the slice
+ * @param   {string}       [axis='z']      For now only 'x', 'y' or 'z' but later it will change to a normal vector
+ * @see THREE.Volume
+ */
+THREE.VolumeSlice = function( volume, index, axis ) {
+
+	var slice = this;
+	/**
+	 * @member {THREE.Volume} volume The associated volume
+	 */
+	this.volume = volume;
+	/**
+	 * @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
+	 */
+	index = index || 0;
+	Object.defineProperty( this, 'index', {
+		get : function() {
+
+			return index;
+
+		},
+		set : function( value ) {
+
+			index = value;
+			slice.geometryNeedsUpdate = true;
+			return index;
+
+		}
+	} );
+	/**
+	 * @member {String} axis The normal axis
+	 */
+	this.axis = axis || 'z';
+
+	/**
+	 * @member {HTMLCanvasElement} canvas The final canvas used for the texture
+	 */
+	/**
+	 * @member {CanvasRenderingContext2D} ctx Context of the canvas
+	 */
+	this.canvas = document.createElement( 'canvas' );
+	/**
+	 * @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
+	 */
+	/**
+	 * @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
+	 */
+	this.canvasBuffer = document.createElement( 'canvas' );
+	this.updateGeometry();
+
+
+	var canvasMap = new THREE.Texture( this.canvas );
+	canvasMap.minFilter = THREE.LinearFilter;
+	canvasMap.wrapS = canvasMap.wrapT = THREE.ClampToEdgeWrapping;
+	var material = new THREE.MeshBasicMaterial( { map: canvasMap, side: THREE.DoubleSide, transparent : true } );
+	/**
+	 * @member {THREE.Mesh} mesh The mesh ready to get used in the scene
+	 */
+	this.mesh = new THREE.Mesh( this.geometry, material );
+	/**
+	 * @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
+	 */
+	this.geometryNeedsUpdate = true;
+	this.repaint();
+
+	/**
+	 * @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
+	 */
+
+	/**
+	 * @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
+	 */
+
+	/**
+	 * @member {Function} sliceAccess Function that allow the slice to access right data
+	 * @see THREE.Volume.extractPerpendicularPlane
+	 * @param {Number} i The first coordinate
+	 * @param {Number} j The second coordinate
+	 * @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
+	 */
+
+
+};
+
+THREE.VolumeSlice.prototype = {
+
+	constructor : THREE.VolumeSlice,
+
+	/**
+	 * @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
+	 * @memberof THREE.VolumeSlice
+	 */
+	repaint : function() {
+
+		if ( this.geometryNeedsUpdate ) {
+
+			this.updateGeometry();
+
+		}
+
+		var iLength = this.iLength,
+		jLength = this.jLength,
+		sliceAccess = this.sliceAccess,
+		volume = this.volume,
+		axis = this.axis,
+		index = this.index,
+		canvas = this.canvasBuffer,
+		ctx = this.ctxBuffer;
+
+
+		// get the imageData and pixel array from the canvas
+		var imgData = ctx.getImageData( 0, 0, iLength, jLength );
+		var data = imgData.data;
+		var volumeData = volume.data;
+		var upperThreshold = volume.upperThreshold;
+		var lowerThreshold = volume.lowerThreshold;
+		var windowLow = volume.windowLow;
+		var windowHigh = volume.windowHigh;
+
+		// manipulate some pixel elements
+		var pixelCount = 0;
+
+		if ( volume.dataType === 'label' ) {
+
+			//this part is currently useless but will be used when colortables will be handled
+			for ( var j = 0; j < jLength; j ++ ) {
+
+				for ( var i = 0; i < iLength; i ++ ) {
+
+					var label = volumeData[ sliceAccess( i, j ) ];
+					label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
+					var color = this.colorMap[ label ];
+					data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
+					data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
+					data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
+					data[ 4 * pixelCount + 3 ] = color & 0xff;
+					pixelCount ++;
+
+				}
+
+			}
+
+		}
+		else {
+
+			for ( var j = 0; j < jLength; j ++ ) {
+
+				for ( var i = 0; i < iLength; i ++ ) {
+
+					var value = volumeData[ sliceAccess( i, j ) ];
+					var alpha = 0xff;
+					//apply threshold
+					alpha = upperThreshold >= value ? ( lowerThreshold <= value ? alpha : 0 ) : 0;
+					//apply window level
+					value = Math.floor( 255 * ( value - windowLow ) / ( windowHigh - windowLow ) );
+					value = value > 255 ? 255 : ( value < 0 ? 0 : value | 0 );
+
+					data[ 4 * pixelCount ] = value;
+					data[ 4 * pixelCount + 1 ] = value;
+					data[ 4 * pixelCount + 2 ] = value;
+					data[ 4 * pixelCount + 3 ] = alpha;
+					pixelCount ++;
+
+				}
+
+			}
+
+		}
+		ctx.putImageData( imgData, 0, 0 );
+		this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );
+
+
+		this.mesh.material.map.needsUpdate = true;
+
+	},
+
+	/**
+	 * @member {Function} Refresh the geometry according to axis and index
+	 * @see THREE.Volume.extractPerpendicularPlane
+	 * @memberof THREE.VolumeSlice
+	 */
+	updateGeometry : function() {
+
+		var extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
+		this.sliceAccess = extracted.sliceAccess;
+		this.jLength = extracted.jLength;
+		this.iLength = extracted.iLength;
+		this.matrix = extracted.matrix;
+
+		this.canvas.width = extracted.planeWidth;
+		this.canvas.height = extracted.planeHeight;
+		this.canvasBuffer.width = this.iLength;
+		this.canvasBuffer.height = this.jLength;
+		this.ctx = this.canvas.getContext( '2d' );
+		this.ctxBuffer = this.canvasBuffer.getContext( '2d' );
+
+		this.geometry = new THREE.PlaneGeometry( extracted.planeWidth, extracted.planeHeight );
+
+		if ( this.mesh ) {
+
+			this.mesh.geometry = this.geometry;
+			//reset mesh matrix
+			this.mesh.matrix = ( new THREE.Matrix4() ).identity();
+			this.mesh.applyMatrix( this.matrix );
+
+		}
+
+		this.geometryNeedsUpdate = false;
+
+	}
+
+};

+ 297 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/WaterShader.js

@@ -0,0 +1,297 @@
+/**
+ * @author jbouny / https://github.com/jbouny
+ *
+ * Work based on :
+ * @author Slayvin / http://slayvin.net : Flat mirror for three.js
+ * @author Stemkoski / http://www.adelphi.edu/~stemkoski : An implementation of water shader based on the flat mirror
+ * @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
+ */
+
+THREE.ShaderLib[ 'water' ] = {
+
+	uniforms: THREE.UniformsUtils.merge( [
+		THREE.UniformsLib[ "fog" ], {
+			"normalSampler":    { value: null },
+			"mirrorSampler":    { value: null },
+			"alpha":            { value: 1.0 },
+			"time":             { value: 0.0 },
+			"distortionScale":  { value: 20.0 },
+			"noiseScale":       { value: 1.0 },
+			"textureMatrix" :   { value: new THREE.Matrix4() },
+			"sunColor":         { value: new THREE.Color( 0x7F7F7F ) },
+			"sunDirection":     { value: new THREE.Vector3( 0.70707, 0.70707, 0 ) },
+			"eye":              { value: new THREE.Vector3() },
+			"waterColor":       { value: new THREE.Color( 0x555555 ) }
+		}
+	] ),
+
+	vertexShader: [
+		'uniform mat4 textureMatrix;',
+		'uniform float time;',
+
+		'varying vec4 mirrorCoord;',
+		'varying vec3 worldPosition;',
+
+		'void main()',
+		'{',
+		'	mirrorCoord = modelMatrix * vec4( position, 1.0 );',
+		'	worldPosition = mirrorCoord.xyz;',
+		'	mirrorCoord = textureMatrix * mirrorCoord;',
+		'	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+		'}'
+	].join( '\n' ),
+
+	fragmentShader: [
+		'precision highp float;',
+
+		'uniform sampler2D mirrorSampler;',
+		'uniform float alpha;',
+		'uniform float time;',
+		'uniform float distortionScale;',
+		'uniform sampler2D normalSampler;',
+		'uniform vec3 sunColor;',
+		'uniform vec3 sunDirection;',
+		'uniform vec3 eye;',
+		'uniform vec3 waterColor;',
+
+		'varying vec4 mirrorCoord;',
+		'varying vec3 worldPosition;',
+
+		'vec4 getNoise( vec2 uv )',
+		'{',
+		'	vec2 uv0 = ( uv / 103.0 ) + vec2(time / 17.0, time / 29.0);',
+		'	vec2 uv1 = uv / 107.0-vec2( time / -19.0, time / 31.0 );',
+		'	vec2 uv2 = uv / vec2( 8907.0, 9803.0 ) + vec2( time / 101.0, time / 97.0 );',
+		'	vec2 uv3 = uv / vec2( 1091.0, 1027.0 ) - vec2( time / 109.0, time / -113.0 );',
+		'	vec4 noise = texture2D( normalSampler, uv0 ) +',
+		'		texture2D( normalSampler, uv1 ) +',
+		'		texture2D( normalSampler, uv2 ) +',
+		'		texture2D( normalSampler, uv3 );',
+		'	return noise * 0.5 - 1.0;',
+		'}',
+
+		'void sunLight( const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor )',
+		'{',
+		'	vec3 reflection = normalize( reflect( -sunDirection, surfaceNormal ) );',
+		'	float direction = max( 0.0, dot( eyeDirection, reflection ) );',
+		'	specularColor += pow( direction, shiny ) * sunColor * spec;',
+		'	diffuseColor += max( dot( sunDirection, surfaceNormal ), 0.0 ) * sunColor * diffuse;',
+		'}',
+
+		THREE.ShaderChunk[ "common" ],
+		THREE.ShaderChunk[ "fog_pars_fragment" ],
+
+		'void main()',
+		'{',
+		'	vec4 noise = getNoise( worldPosition.xz );',
+		'	vec3 surfaceNormal = normalize( noise.xzy * vec3( 1.5, 1.0, 1.5 ) );',
+
+		'	vec3 diffuseLight = vec3(0.0);',
+		'	vec3 specularLight = vec3(0.0);',
+
+		'	vec3 worldToEye = eye-worldPosition;',
+		'	vec3 eyeDirection = normalize( worldToEye );',
+		'	sunLight( surfaceNormal, eyeDirection, 100.0, 2.0, 0.5, diffuseLight, specularLight );',
+
+		'	float distance = length(worldToEye);',
+
+		'	vec2 distortion = surfaceNormal.xz * ( 0.001 + 1.0 / distance ) * distortionScale;',
+		'	vec3 reflectionSample = vec3( texture2D( mirrorSampler, mirrorCoord.xy / mirrorCoord.z + distortion ) );',
+
+		'	float theta = max( dot( eyeDirection, surfaceNormal ), 0.0 );',
+		'	float rf0 = 0.3;',
+		'	float reflectance = rf0 + ( 1.0 - rf0 ) * pow( ( 1.0 - theta ), 5.0 );',
+		'	vec3 scatter = max( 0.0, dot( surfaceNormal, eyeDirection ) ) * waterColor;',
+		'	vec3 albedo = mix( sunColor * diffuseLight * 0.3 + scatter, ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance );',
+		'	vec3 outgoingLight = albedo;',
+			THREE.ShaderChunk[ "fog_fragment" ],
+		'	gl_FragColor = vec4( outgoingLight, alpha );',
+		'}'
+	].join( '\n' )
+
+};
+
+THREE.Water = function ( renderer, camera, scene, options ) {
+
+	THREE.Object3D.call( this );
+	this.name = 'water_' + this.id;
+
+	function optionalParameter ( value, defaultValue ) {
+
+		return value !== undefined ? value : defaultValue;
+
+	}
+
+	options = options || {};
+
+	this.matrixNeedsUpdate = true;
+
+	var width = optionalParameter( options.textureWidth, 512 );
+	var height = optionalParameter( options.textureHeight, 512 );
+	this.clipBias = optionalParameter( options.clipBias, 0.0 );
+	this.alpha = optionalParameter( options.alpha, 1.0 );
+	this.time = optionalParameter( options.time, 0.0 );
+	this.normalSampler = optionalParameter( options.waterNormals, null );
+	this.sunDirection = optionalParameter( options.sunDirection, new THREE.Vector3( 0.70707, 0.70707, 0.0 ) );
+	this.sunColor = new THREE.Color( optionalParameter( options.sunColor, 0xffffff ) );
+	this.waterColor = new THREE.Color( optionalParameter( options.waterColor, 0x7F7F7F ) );
+	this.eye = optionalParameter( options.eye, new THREE.Vector3( 0, 0, 0 ) );
+	this.distortionScale = optionalParameter( options.distortionScale, 20.0 );
+	this.side = optionalParameter( options.side, THREE.FrontSide );
+	this.fog = optionalParameter( options.fog, false );
+
+	this.renderer = renderer;
+	this.scene = scene;
+	this.mirrorPlane = new THREE.Plane();
+	this.normal = new THREE.Vector3( 0, 0, 1 );
+	this.mirrorWorldPosition = new THREE.Vector3();
+	this.cameraWorldPosition = new THREE.Vector3();
+	this.rotationMatrix = new THREE.Matrix4();
+	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
+	this.clipPlane = new THREE.Vector4();
+
+	if ( camera instanceof THREE.PerspectiveCamera ) {
+
+		this.camera = camera;
+
+	} else {
+
+		this.camera = new THREE.PerspectiveCamera();
+		console.log( this.name + ': camera is not a Perspective Camera!' );
+
+	}
+
+	this.textureMatrix = new THREE.Matrix4();
+
+	this.mirrorCamera = this.camera.clone();
+
+	this.renderTarget = new THREE.WebGLRenderTarget( width, height );
+	this.renderTarget2 = new THREE.WebGLRenderTarget( width, height );
+
+	var mirrorShader = THREE.ShaderLib[ "water" ];
+	var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
+
+	this.material = new THREE.ShaderMaterial( {
+		fragmentShader: mirrorShader.fragmentShader,
+		vertexShader: mirrorShader.vertexShader,
+		uniforms: mirrorUniforms,
+		transparent: true,
+		side: this.side,
+		fog: this.fog
+	} );
+
+	this.material.uniforms.mirrorSampler.value = this.renderTarget.texture;
+	this.material.uniforms.textureMatrix.value = this.textureMatrix;
+	this.material.uniforms.alpha.value = this.alpha;
+	this.material.uniforms.time.value = this.time;
+	this.material.uniforms.normalSampler.value = this.normalSampler;
+	this.material.uniforms.sunColor.value = this.sunColor;
+	this.material.uniforms.waterColor.value = this.waterColor;
+	this.material.uniforms.sunDirection.value = this.sunDirection;
+	this.material.uniforms.distortionScale.value = this.distortionScale;
+
+	this.material.uniforms.eye.value = this.eye;
+
+	if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
+
+		this.renderTarget.texture.generateMipmaps = false;
+		this.renderTarget.texture.minFilter = THREE.LinearFilter;
+		this.renderTarget2.texture.generateMipmaps = false;
+		this.renderTarget2.texture.minFilter = THREE.LinearFilter;
+
+	}
+
+	this.updateTextureMatrix();
+	this.render();
+
+};
+
+THREE.Water.prototype = Object.create( THREE.Mirror.prototype );
+THREE.Water.prototype.constructor = THREE.Water;
+
+
+THREE.Water.prototype.updateTextureMatrix = function () {
+
+	function sign( x ) {
+
+		return x ? x < 0 ? - 1 : 1 : 0;
+
+	}
+
+	this.updateMatrixWorld();
+	this.camera.updateMatrixWorld();
+
+	this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
+	this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
+
+	this.rotationMatrix.extractRotation( this.matrixWorld );
+
+	this.normal.set( 0, 0, 1 );
+	this.normal.applyMatrix4( this.rotationMatrix );
+
+	var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
+	view.reflect( this.normal ).negate();
+	view.add( this.mirrorWorldPosition );
+
+	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
+
+	this.lookAtPosition.set( 0, 0, - 1 );
+	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
+	this.lookAtPosition.add( this.cameraWorldPosition );
+
+	var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
+	target.reflect( this.normal ).negate();
+	target.add( this.mirrorWorldPosition );
+
+	this.up.set( 0, - 1, 0 );
+	this.up.applyMatrix4( this.rotationMatrix );
+	this.up.reflect( this.normal ).negate();
+
+	this.mirrorCamera.position.copy( view );
+	this.mirrorCamera.up = this.up;
+	this.mirrorCamera.lookAt( target );
+	this.mirrorCamera.aspect = this.camera.aspect;
+
+	this.mirrorCamera.updateProjectionMatrix();
+	this.mirrorCamera.updateMatrixWorld();
+	this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld );
+
+	// Update the texture matrix
+	this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
+							0.0, 0.5, 0.0, 0.5,
+							0.0, 0.0, 0.5, 0.5,
+							0.0, 0.0, 0.0, 1.0 );
+	this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
+	this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse );
+
+	// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
+	// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
+	this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
+	this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
+
+	this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
+
+	var q = new THREE.Vector4();
+	var projectionMatrix = this.mirrorCamera.projectionMatrix;
+
+	q.x = ( sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+	q.y = ( sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+	q.z = - 1.0;
+	q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
+
+	// Calculate the scaled plane vector
+	var c = new THREE.Vector4();
+	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
+
+	// Replacing the third row of the projection matrix
+	projectionMatrix.elements[ 2 ] = c.x;
+	projectionMatrix.elements[ 6 ] = c.y;
+	projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
+	projectionMatrix.elements[ 14 ] = c.w;
+
+	var worldCoordinates = new THREE.Vector3();
+	worldCoordinates.setFromMatrixPosition( this.camera.matrixWorld );
+	this.eye = worldCoordinates;
+	this.material.uniforms.eye.value = this.eye;
+
+};

+ 416 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/animation/CCDIKSolver.js

@@ -0,0 +1,416 @@
+/**
+ * @author takahiro / https://github.com/takahirox
+ *
+ * CCD Algorithm
+ *  https://sites.google.com/site/auraliusproject/ccd-algorithm
+ *
+ * mesh.geometry needs to have iks array.
+ *
+ * // ik parameter example
+ * //
+ * // target, effector, index in links are bone index in skeleton.
+ * // the bones relation should be
+ * // <-- parent                                  child -->
+ * // links[ n ], links[ n - 1 ], ..., links[ 0 ], effector
+ * ik = {
+ *	target: 1,
+ *	effector: 2,
+ *	links: [ { index: 5, limitation: new THREE.Vector3( 1, 0, 0 ) }, { index: 4, enabled: false }, { index : 3 } ],
+ *	iteration: 10,
+ *	minAngle: 0.0,
+ *	maxAngle: 1.0,
+ * };
+ */
+
+THREE.CCDIKSolver = function ( mesh ) {
+
+	this.mesh = mesh;
+
+	this._valid();
+
+};
+
+THREE.CCDIKSolver.prototype = {
+
+	constructor: THREE.CCDIKSolver,
+
+	_valid: function () {
+
+		var iks = this.mesh.geometry.iks;
+		var bones = this.mesh.skeleton.bones;
+
+		for ( var i = 0, il = iks.length; i < il; i ++ ) {
+
+			var ik = iks[ i ];
+
+			var effector = bones[ ik.effector ];
+
+			var links = ik.links;
+
+			var link0, link1;
+
+			link0 = effector;
+
+			for ( var j = 0, jl = links.length; j < jl; j ++ ) {
+
+				link1 = bones[ links[ j ].index ];
+
+				if ( link0.parent !== link1 ) {
+
+					console.warn( 'THREE.CCDIKSolver: bone ' + link0.name + ' is not the child of bone ' + link1.name );
+
+				}
+
+				link0 = link1;
+
+			}
+
+		}
+
+	},
+
+	/*
+	 * save the bone matrices before solving IK.
+	 * they're used for generating VMD and VPD.
+	 */
+	_saveOriginalBonesInfo: function () {
+
+		var bones = this.mesh.skeleton.bones;
+
+		for ( var i = 0, il = bones.length; i < il; i ++ ) {
+
+			var bone = bones[ i ];
+
+			if ( bone.userData.ik === undefined ) bone.userData.ik = {};
+
+			bone.userData.ik.originalMatrix = bone.matrix.toArray();
+
+		}
+
+	},
+
+	update: function ( saveOriginalBones ) {
+
+		var q = new THREE.Quaternion();
+
+		var targetPos = new THREE.Vector3();
+		var targetVec = new THREE.Vector3();
+		var effectorPos = new THREE.Vector3();
+		var effectorVec = new THREE.Vector3();
+		var linkPos = new THREE.Vector3();
+		var invLinkQ = new THREE.Quaternion();
+		var axis = new THREE.Vector3();
+
+		var bones = this.mesh.skeleton.bones;
+		var iks = this.mesh.geometry.iks;
+
+		var boneParams = this.mesh.geometry.bones;
+
+		// for reference overhead reduction in loop
+		var math = Math;
+
+		this.mesh.updateMatrixWorld( true );
+
+		if ( saveOriginalBones === true ) this._saveOriginalBonesInfo();
+
+		for ( var i = 0, il = iks.length; i < il; i++ ) {
+
+			var ik = iks[ i ];
+			var effector = bones[ ik.effector ];
+			var target = bones[ ik.target ];
+
+			// don't use getWorldPosition() here for the performance
+			// because it calls updateMatrixWorld( true ) inside.
+			targetPos.setFromMatrixPosition( target.matrixWorld );
+
+			var links = ik.links;
+			var iteration = ik.iteration !== undefined ? ik.iteration : 1;
+
+			for ( var j = 0; j < iteration; j++ ) {
+
+				var rotated = false;
+
+				for ( var k = 0, kl = links.length; k < kl; k++ ) {
+
+					var link = bones[ links[ k ].index ];
+
+					// skip this link and following links.
+					// this skip is used for MMD performance optimization.
+					if ( links[ k ].enabled === false ) break;
+
+					var limitation = links[ k ].limitation;
+
+					// don't use getWorldPosition/Quaternion() here for the performance
+					// because they call updateMatrixWorld( true ) inside.
+					linkPos.setFromMatrixPosition( link.matrixWorld );
+					invLinkQ.setFromRotationMatrix( link.matrixWorld ).inverse();
+					effectorPos.setFromMatrixPosition( effector.matrixWorld );
+
+					// work in link world
+					effectorVec.subVectors( effectorPos, linkPos );
+					effectorVec.applyQuaternion( invLinkQ );
+					effectorVec.normalize();
+
+					targetVec.subVectors( targetPos, linkPos );
+					targetVec.applyQuaternion( invLinkQ );
+					targetVec.normalize();
+
+					var angle = targetVec.dot( effectorVec );
+
+					if ( angle > 1.0 ) {
+
+						angle = 1.0;
+
+					} else if ( angle < -1.0 ) {
+
+						angle = -1.0;
+
+					}
+
+					angle = math.acos( angle );
+
+					// skip if changing angle is too small to prevent vibration of bone
+					// Refer to http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
+					if ( angle < 1e-5 ) continue;
+
+					if ( ik.minAngle !== undefined && angle < ik.minAngle ) {
+
+						angle = ik.minAngle;
+
+					}
+
+					if ( ik.maxAngle !== undefined && angle > ik.maxAngle ) {
+
+						angle = ik.maxAngle;
+
+					}
+
+					axis.crossVectors( effectorVec, targetVec );
+					axis.normalize();
+
+					q.setFromAxisAngle( axis, angle );
+					link.quaternion.multiply( q );
+
+					// TODO: re-consider the limitation specification
+					if ( limitation !== undefined ) {
+
+						var c = link.quaternion.w;
+
+						if ( c > 1.0 ) {
+
+							c = 1.0;
+
+						}
+
+						var c2 = math.sqrt( 1 - c * c );
+						link.quaternion.set( limitation.x * c2,
+						                     limitation.y * c2,
+						                     limitation.z * c2,
+						                     c );
+
+					}
+
+					link.updateMatrixWorld( true );
+					rotated = true;
+
+				}
+
+				if ( ! rotated ) break;
+
+			}
+
+		}
+
+		// just in case
+		this.mesh.updateMatrixWorld( true );
+
+	}
+
+};
+
+
+THREE.CCDIKHelper = function ( mesh ) {
+
+	if ( mesh.geometry.iks === undefined || mesh.skeleton === undefined ) {
+
+		throw 'THREE.CCDIKHelper requires iks in mesh.geometry and skeleton in mesh.';
+
+	}
+
+	THREE.Object3D.call( this );
+
+	this.root = mesh;
+
+	this.matrix = mesh.matrixWorld;
+	this.matrixAutoUpdate = false;
+
+	this.sphereGeometry = new THREE.SphereBufferGeometry( 0.25, 16, 8 );
+
+	this.targetSphereMaterial = new THREE.MeshBasicMaterial( {
+		color: new THREE.Color( 0xff8888 ),
+		depthTest: false,
+		depthWrite: false,
+		transparent: true
+	} );
+
+	this.effectorSphereMaterial = new THREE.MeshBasicMaterial( {
+		color: new THREE.Color( 0x88ff88 ),
+		depthTest: false,
+		depthWrite: false,
+		transparent: true
+	} );
+
+	this.linkSphereMaterial = new THREE.MeshBasicMaterial( {
+		color: new THREE.Color( 0x8888ff ),
+		depthTest: false,
+		depthWrite: false,
+		transparent: true
+	} );
+
+	this.lineMaterial = new THREE.LineBasicMaterial( {
+		color: new THREE.Color( 0xff0000 ),
+		depthTest: false,
+		depthWrite: false,
+		transparent: true
+	} );
+
+	this._init();
+	this.update();
+
+};
+
+THREE.CCDIKHelper.prototype = Object.create( THREE.Object3D.prototype );
+THREE.CCDIKHelper.prototype.constructor = THREE.CCDIKHelper;
+
+THREE.CCDIKHelper.prototype._init = function () {
+
+	var self = this;
+	var mesh = this.root;
+	var iks = mesh.geometry.iks;
+
+	function createLineGeometry( ik ) {
+
+		var geometry = new THREE.BufferGeometry();
+		var vertices = new Float32Array( ( 2 + ik.links.length ) * 3 );
+		geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+
+		return geometry;
+
+	}
+
+	function createTargetMesh() {
+
+		return new THREE.Mesh( self.sphereGeometry, self.targetSphereMaterial );
+
+	}
+
+	function createEffectorMesh() {
+
+		return new THREE.Mesh( self.sphereGeometry, self.effectorSphereMaterial );
+
+	}
+
+	function createLinkMesh() {
+
+		return new THREE.Mesh( self.sphereGeometry, self.linkSphereMaterial );
+
+	}
+
+	function createLine( ik ) {
+
+		return new THREE.Line( createLineGeometry( ik ), self.lineMaterial );
+
+	}
+
+	for ( var i = 0, il = iks.length; i < il; i ++ ) {
+
+		var ik = iks[ i ];
+
+		this.add( createTargetMesh() );
+		this.add( createEffectorMesh() );
+
+		for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
+
+			this.add( createLinkMesh() );
+
+		}
+
+		this.add( createLine( ik ) );
+
+	}
+
+};
+
+THREE.CCDIKHelper.prototype.update = function () {
+
+	var offset = 0;
+
+	var mesh = this.root;
+	var iks = mesh.geometry.iks;
+	var bones = mesh.skeleton.bones;
+
+	var matrixWorldInv = new THREE.Matrix4().getInverse( mesh.matrixWorld );
+	var vector = new THREE.Vector3();
+
+	function getPosition( bone ) {
+
+		vector.setFromMatrixPosition( bone.matrixWorld );
+		vector.applyMatrix4( matrixWorldInv );
+
+		return vector;
+
+	}
+
+	function setPositionOfBoneToAttributeArray( array, index, bone ) {
+
+		var v = getPosition( bone );
+
+		array[ index * 3 + 0 ] = v.x;
+		array[ index * 3 + 1 ] = v.y;
+		array[ index * 3 + 2 ] = v.z;
+
+	}
+
+	for ( var i = 0, il = iks.length; i < il; i ++ ) {
+
+		var ik = iks[ i ];
+
+		var targetBone = bones[ ik.target ];
+		var effectorBone = bones[ ik.effector ];
+
+		var targetMesh = this.children[ offset ++ ];
+		var effectorMesh = this.children[ offset ++ ];
+
+		targetMesh.position.copy( getPosition( targetBone ) );
+		effectorMesh.position.copy( getPosition( effectorBone ) );
+
+		for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
+
+			var link = ik.links[ j ];
+			var linkBone = bones[ link.index ];
+
+			var linkMesh = this.children[ offset ++ ];
+
+			linkMesh.position.copy( getPosition( linkBone ) );
+
+		}
+
+		var line = this.children[ offset ++ ];
+		var array = line.geometry.attributes.position.array;
+
+		setPositionOfBoneToAttributeArray( array, 0, targetBone );
+		setPositionOfBoneToAttributeArray( array, 1, effectorBone );
+
+		for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
+
+			var link = ik.links[ j ];
+			var linkBone = bones[ link.index ];
+			setPositionOfBoneToAttributeArray( array, j + 2, linkBone );
+
+		}
+
+		line.geometry.attributes.position.needsUpdate = true;
+
+	}
+
+};

+ 1200 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/animation/MMDPhysics.js

@@ -0,0 +1,1200 @@
+/**
+ * @author takahiro / https://github.com/takahirox
+ *
+ * Dependencies
+ *  - Ammo.js https://github.com/kripken/ammo.js
+ *
+ * MMD specific Physics class.
+ *
+ * See THREE.MMDLoader for the passed parameter list of RigidBody/Constraint.
+ *
+ * Requirement:
+ *  - don't change object's scale from (1,1,1) after setting physics to object
+ *
+ * TODO
+ *  - optimize for the performance
+ *  - use Physijs http://chandlerprall.github.io/Physijs/
+ *    and improve the performance by making use of Web worker.
+ *  - if possible, make this class being non-MMD specific.
+ *  - object scale change support
+ */
+
+THREE.MMDPhysics = function ( mesh, params ) {
+
+	if ( params === undefined ) params = {};
+
+	this.mesh = mesh;
+	this.helper = new THREE.MMDPhysics.ResourceHelper();
+
+	/*
+	 * I don't know why but 1/60 unitStep easily breaks models
+	 * so I set it 1/65 so far.
+	 * Don't set too small unitStep because
+	 * the smaller unitStep can make the performance worse.
+	 */
+	this.unitStep = ( params.unitStep !== undefined ) ? params.unitStep : 1 / 65;
+	this.maxStepNum = ( params.maxStepNum !== undefined ) ? params.maxStepNum : 3;
+
+	this.world = params.world !== undefined ? params.world : null;
+	this.bodies = [];
+	this.constraints = [];
+
+	this.init( mesh );
+
+};
+
+THREE.MMDPhysics.prototype = {
+
+	constructor: THREE.MMDPhysics,
+
+	init: function ( mesh ) {
+
+		var parent = mesh.parent;
+
+		if ( parent !== null ) {
+
+			parent.remove( mesh );
+
+		}
+
+		var currentPosition = mesh.position.clone();
+		var currentRotation = mesh.rotation.clone();
+		var currentScale = mesh.scale.clone();
+
+		mesh.position.set( 0, 0, 0 );
+		mesh.rotation.set( 0, 0, 0 );
+		mesh.scale.set( 1, 1, 1 );
+
+		mesh.updateMatrixWorld( true );
+
+		if ( this.world === null ) this.initWorld();
+		this.initRigidBodies();
+		this.initConstraints();
+
+		if ( parent !== null ) {
+
+			parent.add( mesh );
+
+		}
+
+		mesh.position.copy( currentPosition );
+		mesh.rotation.copy( currentRotation );
+		mesh.scale.copy( currentScale );
+
+		mesh.updateMatrixWorld( true );
+
+		this.reset();
+
+	},
+
+	initWorld: function () {
+
+		var config = new Ammo.btDefaultCollisionConfiguration();
+		var dispatcher = new Ammo.btCollisionDispatcher( config );
+		var cache = new Ammo.btDbvtBroadphase();
+		var solver = new Ammo.btSequentialImpulseConstraintSolver();
+		var world = new Ammo.btDiscreteDynamicsWorld( dispatcher, cache, solver, config );
+		world.setGravity( new Ammo.btVector3( 0, -9.8 * 10, 0 ) );
+		this.world = world;
+
+	},
+
+	initRigidBodies: function () {
+
+		var bodies = this.mesh.geometry.rigidBodies;
+
+		for ( var i = 0; i < bodies.length; i++ ) {
+
+			var b = new THREE.MMDPhysics.RigidBody( this.mesh, this.world, bodies[ i ], this.helper );
+			this.bodies.push( b );
+
+		}
+
+	},
+
+	initConstraints: function () {
+
+		var constraints = this.mesh.geometry.constraints;
+
+		for ( var i = 0; i < constraints.length; i++ ) {
+
+			var params = constraints[ i ];
+			var bodyA = this.bodies[ params.rigidBodyIndex1 ];
+			var bodyB = this.bodies[ params.rigidBodyIndex2 ];
+			var c = new THREE.MMDPhysics.Constraint( this.mesh, this.world, bodyA, bodyB, params, this.helper );
+			this.constraints.push( c );
+
+		}
+
+
+	},
+
+	update: function ( delta ) {
+
+		this.updateRigidBodies();
+		this.stepSimulation( delta );
+		this.updateBones();
+
+	},
+
+	stepSimulation: function ( delta ) {
+
+		var unitStep = this.unitStep;
+		var stepTime = delta;
+		var maxStepNum = ( ( delta / unitStep ) | 0 ) + 1;
+
+		if ( stepTime < unitStep ) {
+
+			stepTime = unitStep;
+			maxStepNum = 1;
+
+		}
+
+		if ( maxStepNum > this.maxStepNum ) {
+
+			maxStepNum = this.maxStepNum;
+
+		}
+
+		this.world.stepSimulation( stepTime, maxStepNum, unitStep );
+
+	},
+
+	updateRigidBodies: function () {
+
+		for ( var i = 0; i < this.bodies.length; i++ ) {
+
+			this.bodies[ i ].updateFromBone();
+
+		}
+
+	},
+
+	updateBones: function () {
+
+		for ( var i = 0; i < this.bodies.length; i++ ) {
+
+			this.bodies[ i ].updateBone();
+
+		}
+
+	},
+
+	reset: function () {
+
+		for ( var i = 0; i < this.bodies.length; i++ ) {
+
+			this.bodies[ i ].reset();
+
+		}
+
+	},
+
+	warmup: function ( cycles ) {
+
+		for ( var i = 0; i < cycles; i++ ) {
+
+			this.update( 1 / 60 );
+
+		}
+
+	}
+
+};
+
+/**
+ * This helper class responsibilies are
+ *
+ * 1. manage Ammo.js and Three.js object resources and
+ *    improve the performance and the memory consumption by
+ *    reusing objects.
+ *
+ * 2. provide simple Ammo object operations.
+ */
+THREE.MMDPhysics.ResourceHelper = function () {
+
+	// for Three.js
+	this.threeVector3s = [];
+	this.threeMatrix4s = [];
+	this.threeQuaternions = [];
+	this.threeEulers = [];
+
+	// for Ammo.js
+	this.transforms = [];
+	this.quaternions = [];
+	this.vector3s = [];
+
+};
+
+THREE.MMDPhysics.ResourceHelper.prototype = {
+
+	allocThreeVector3: function () {
+
+		return ( this.threeVector3s.length > 0 ) ? this.threeVector3s.pop() : new THREE.Vector3();
+
+	},
+
+	freeThreeVector3: function ( v ) {
+
+		this.threeVector3s.push( v );
+
+	},
+
+	allocThreeMatrix4: function () {
+
+		return ( this.threeMatrix4s.length > 0 ) ? this.threeMatrix4s.pop() : new THREE.Matrix4();
+
+	},
+
+	freeThreeMatrix4: function ( m ) {
+
+		this.threeMatrix4s.push( m );
+
+	},
+
+	allocThreeQuaternion: function () {
+
+		return ( this.threeQuaternions.length > 0 ) ? this.threeQuaternions.pop() : new THREE.Quaternion();
+
+	},
+
+	freeThreeQuaternion: function ( q ) {
+
+		this.threeQuaternions.push( q );
+
+	},
+
+	allocThreeEuler: function () {
+
+		return ( this.threeEulers.length > 0 ) ? this.threeEulers.pop() : new THREE.Euler();
+
+	},
+
+	freeThreeEuler: function ( e ) {
+
+		this.threeEulers.push( e );
+
+	},
+
+	allocTransform: function () {
+
+		return ( this.transforms.length > 0 ) ? this.transforms.pop() : new Ammo.btTransform();
+
+	},
+
+	freeTransform: function ( t ) {
+
+		this.transforms.push( t );
+
+	},
+
+	allocQuaternion: function () {
+
+		return ( this.quaternions.length > 0 ) ? this.quaternions.pop() : new Ammo.btQuaternion();
+
+	},
+
+	freeQuaternion: function ( q ) {
+
+		this.quaternions.push( q );
+
+	},
+
+	allocVector3: function () {
+
+		return ( this.vector3s.length > 0 ) ? this.vector3s.pop() : new Ammo.btVector3();
+
+	},
+
+	freeVector3: function ( v ) {
+
+		this.vector3s.push( v );
+
+	},
+
+	setIdentity: function ( t ) {
+
+		t.setIdentity();
+
+	},
+
+	getBasis: function ( t ) {
+
+		var q = this.allocQuaternion();
+		t.getBasis().getRotation( q );
+		return q;
+
+	},
+
+	getBasisAsMatrix3: function ( t ) {
+
+		var q = this.getBasis( t );
+		var m = this.quaternionToMatrix3( q );
+		this.freeQuaternion( q );
+		return m;
+
+	},
+
+	getOrigin: function( t ) {
+
+		return t.getOrigin();
+
+	},
+
+	setOrigin: function( t, v ) {
+
+		t.getOrigin().setValue( v.x(), v.y(), v.z() );
+
+	},
+
+	copyOrigin: function( t1, t2 ) {
+
+		var o = t2.getOrigin();
+		this.setOrigin( t1, o );
+
+	},
+
+	setBasis: function( t, q ) {
+
+		t.setRotation( q );
+
+	},
+
+	setBasisFromMatrix3: function( t, m ) {
+
+		var q = this.matrix3ToQuaternion( m );
+		this.setBasis( t, q );
+		this.freeQuaternion( q );
+
+	},
+
+	setOriginFromArray3: function ( t, a ) {
+
+		t.getOrigin().setValue( a[ 0 ], a[ 1 ], a[ 2 ] );
+
+	},
+
+	setBasisFromArray3: function ( t, a ) {
+
+		var thQ = this.allocThreeQuaternion();
+		var thE = this.allocThreeEuler();
+		thE.set( a[ 0 ], a[ 1 ], a[ 2 ] );
+		this.setBasisFromArray4( t, thQ.setFromEuler( thE ).toArray() );
+
+		this.freeThreeEuler( thE );
+		this.freeThreeQuaternion( thQ );
+
+	},
+
+	setBasisFromArray4: function ( t, a ) {
+
+		var q = this.array4ToQuaternion( a );
+		this.setBasis( t, q );
+		this.freeQuaternion( q );
+
+	},
+
+	array4ToQuaternion: function( a ) {
+
+		var q = this.allocQuaternion();
+		q.setX( a[ 0 ] );
+		q.setY( a[ 1 ] );
+		q.setZ( a[ 2 ] );
+		q.setW( a[ 3 ] );
+		return q;
+
+	},
+
+	multiplyTransforms: function ( t1, t2 ) {
+
+		var t = this.allocTransform();
+		this.setIdentity( t );
+
+		var m1 = this.getBasisAsMatrix3( t1 );
+		var m2 = this.getBasisAsMatrix3( t2 );
+
+		var o1 = this.getOrigin( t1 );
+		var o2 = this.getOrigin( t2 );
+
+		var v1 = this.multiplyMatrix3ByVector3( m1, o2 );
+		var v2 = this.addVector3( v1, o1 );
+		this.setOrigin( t, v2 );
+
+		var m3 = this.multiplyMatrices3( m1, m2 );
+		this.setBasisFromMatrix3( t, m3 );
+
+		this.freeVector3( v1 );
+		this.freeVector3( v2 );
+
+		return t;
+
+	},
+
+	inverseTransform: function ( t ) {
+
+		var t2 = this.allocTransform();
+
+		var m1 = this.getBasisAsMatrix3( t );
+		var o = this.getOrigin( t );
+
+		var m2 = this.transposeMatrix3( m1 );
+		var v1 = this.negativeVector3( o );
+		var v2 = this.multiplyMatrix3ByVector3( m2, v1 );
+
+		this.setOrigin( t2, v2 );
+		this.setBasisFromMatrix3( t2, m2 );
+
+		this.freeVector3( v1 );
+		this.freeVector3( v2 );
+
+		return t2;
+
+	},
+
+	multiplyMatrices3: function ( m1, m2 ) {
+
+		var m3 = [];
+
+		var v10 = this.rowOfMatrix3( m1, 0 );
+		var v11 = this.rowOfMatrix3( m1, 1 );
+		var v12 = this.rowOfMatrix3( m1, 2 );
+
+		var v20 = this.columnOfMatrix3( m2, 0 );
+		var v21 = this.columnOfMatrix3( m2, 1 );
+		var v22 = this.columnOfMatrix3( m2, 2 );
+
+		m3[ 0 ] = this.dotVectors3( v10, v20 );
+		m3[ 1 ] = this.dotVectors3( v10, v21 );
+		m3[ 2 ] = this.dotVectors3( v10, v22 );
+		m3[ 3 ] = this.dotVectors3( v11, v20 );
+		m3[ 4 ] = this.dotVectors3( v11, v21 );
+		m3[ 5 ] = this.dotVectors3( v11, v22 );
+		m3[ 6 ] = this.dotVectors3( v12, v20 );
+		m3[ 7 ] = this.dotVectors3( v12, v21 );
+		m3[ 8 ] = this.dotVectors3( v12, v22 );
+
+		this.freeVector3( v10 );
+		this.freeVector3( v11 );
+		this.freeVector3( v12 );
+		this.freeVector3( v20 );
+		this.freeVector3( v21 );
+		this.freeVector3( v22 );
+
+		return m3;
+
+	},
+
+	addVector3: function( v1, v2 ) {
+
+		var v = this.allocVector3();
+		v.setValue( v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z() );
+		return v;
+
+	},
+
+	dotVectors3: function( v1, v2 ) {
+
+		return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z();
+
+	},
+
+	rowOfMatrix3: function( m, i ) {
+
+		var v = this.allocVector3();
+		v.setValue( m[ i * 3 + 0 ], m[ i * 3 + 1 ], m[ i * 3 + 2 ] );
+		return v;
+
+	},
+
+	columnOfMatrix3: function( m, i ) {
+
+		var v = this.allocVector3();
+		v.setValue( m[ i + 0 ], m[ i + 3 ], m[ i + 6 ] );
+		return v;
+
+	},
+
+	negativeVector3: function( v ) {
+
+		var v2 = this.allocVector3();
+		v2.setValue( -v.x(), -v.y(), -v.z() );
+		return v2;
+
+	},
+
+	multiplyMatrix3ByVector3: function ( m, v ) {
+
+		var v4 = this.allocVector3();
+
+		var v0 = this.rowOfMatrix3( m, 0 );
+		var v1 = this.rowOfMatrix3( m, 1 );
+		var v2 = this.rowOfMatrix3( m, 2 );
+		var x = this.dotVectors3( v0, v );
+		var y = this.dotVectors3( v1, v );
+		var z = this.dotVectors3( v2, v );
+
+		v4.setValue( x, y, z );
+
+		this.freeVector3( v0 );
+		this.freeVector3( v1 );
+		this.freeVector3( v2 );
+
+		return v4;
+
+	},
+
+	transposeMatrix3: function( m ) {
+
+		var m2 = [];
+		m2[ 0 ] = m[ 0 ];
+		m2[ 1 ] = m[ 3 ];
+		m2[ 2 ] = m[ 6 ];
+		m2[ 3 ] = m[ 1 ];
+		m2[ 4 ] = m[ 4 ];
+		m2[ 5 ] = m[ 7 ];
+		m2[ 6 ] = m[ 2 ];
+		m2[ 7 ] = m[ 5 ];
+		m2[ 8 ] = m[ 8 ];
+		return m2;
+
+	},
+
+	quaternionToMatrix3: function ( q ) {
+
+		var m = [];
+
+		var x = q.x();
+		var y = q.y();
+		var z = q.z();
+		var w = q.w();
+
+		var xx = x * x;
+		var yy = y * y;
+		var zz = z * z;
+
+		var xy = x * y;
+		var yz = y * z;
+		var zx = z * x;
+
+		var xw = x * w;
+		var yw = y * w;
+		var zw = z * w;
+
+		m[ 0 ] = 1 - 2 * ( yy + zz );
+		m[ 1 ] = 2 * ( xy - zw );
+		m[ 2 ] = 2 * ( zx + yw );
+		m[ 3 ] = 2 * ( xy + zw );
+		m[ 4 ] = 1 - 2 * ( zz + xx );
+		m[ 5 ] = 2 * ( yz - xw );
+		m[ 6 ] = 2 * ( zx - yw );
+		m[ 7 ] = 2 * ( yz + xw );
+		m[ 8 ] = 1 - 2 * ( xx + yy );
+
+		return m;
+
+	},
+
+	matrix3ToQuaternion: function( m ) {
+
+		var t = m[ 0 ] + m[ 4 ] + m[ 8 ];
+		var s, x, y, z, w;
+
+		if( t > 0 ) {
+
+			s = Math.sqrt( t + 1.0 ) * 2;
+			w = 0.25 * s;
+			x = ( m[ 7 ] - m[ 5 ] ) / s;
+			y = ( m[ 2 ] - m[ 6 ] ) / s; 
+			z = ( m[ 3 ] - m[ 1 ] ) / s; 
+
+		} else if( ( m[ 0 ] > m[ 4 ] ) && ( m[ 0 ] > m[ 8 ] ) ) {
+
+			s = Math.sqrt( 1.0 + m[ 0 ] - m[ 4 ] - m[ 8 ] ) * 2;
+			w = ( m[ 7 ] - m[ 5 ] ) / s;
+			x = 0.25 * s;
+			y = ( m[ 1 ] + m[ 3 ] ) / s;
+			z = ( m[ 2 ] + m[ 6 ] ) / s;
+
+		} else if( m[ 4 ] > m[ 8 ] ) {
+
+			s = Math.sqrt( 1.0 + m[ 4 ] - m[ 0 ] - m[ 8 ] ) * 2;
+			w = ( m[ 2 ] - m[ 6 ] ) / s;
+			x = ( m[ 1 ] + m[ 3 ] ) / s;
+			y = 0.25 * s;
+			z = ( m[ 5 ] + m[ 7 ] ) / s;
+
+		} else {
+
+			s = Math.sqrt( 1.0 + m[ 8 ] - m[ 0 ] - m[ 4 ] ) * 2;
+			w = ( m[ 3 ] - m[ 1 ] ) / s;
+			x = ( m[ 2 ] + m[ 6 ] ) / s;
+			y = ( m[ 5 ] + m[ 7 ] ) / s;
+			z = 0.25 * s;
+
+		}
+
+		var q = this.allocQuaternion();
+		q.setX( x );
+		q.setY( y );
+		q.setZ( z );
+		q.setW( w );
+		return q;
+
+	}
+
+};
+
+THREE.MMDPhysics.RigidBody = function ( mesh, world, params, helper ) {
+
+	this.mesh  = mesh;
+	this.world = world;
+	this.params = params;
+	this.helper = helper;
+
+	this.body = null;
+	this.bone = null;
+	this.boneOffsetForm = null;
+	this.boneOffsetFormInverse = null;
+
+	this.init();
+
+};
+
+THREE.MMDPhysics.RigidBody.prototype = {
+
+	constructor: THREE.MMDPhysics.RigidBody,
+
+	init: function () {
+
+		function generateShape( p ) {
+
+			switch( p.shapeType ) {
+
+				case 0:
+					return new Ammo.btSphereShape( p.width );
+
+				case 1:
+					return new Ammo.btBoxShape( new Ammo.btVector3( p.width, p.height, p.depth ) );
+
+				case 2:
+					return new Ammo.btCapsuleShape( p.width, p.height );
+
+				default:
+					throw 'unknown shape type ' + p.shapeType;
+
+			}
+
+		}
+
+		var helper = this.helper;
+		var params = this.params;
+		var bones = this.mesh.skeleton.bones;
+		var bone = ( params.boneIndex === -1 ) ? new THREE.Bone() : bones[ params.boneIndex ];
+
+		var shape = generateShape( params );
+		var weight = ( params.type === 0 ) ? 0 : params.weight;
+		var localInertia = helper.allocVector3();
+		localInertia.setValue( 0, 0, 0 );
+
+		if( weight !== 0 ) {
+
+			shape.calculateLocalInertia( weight, localInertia );
+
+		}
+
+		var boneOffsetForm = helper.allocTransform();
+		helper.setIdentity( boneOffsetForm );
+		helper.setOriginFromArray3( boneOffsetForm, params.position );
+		helper.setBasisFromArray3( boneOffsetForm, params.rotation );
+
+		var boneForm = helper.allocTransform();
+		helper.setIdentity( boneForm );
+		helper.setOriginFromArray3( boneForm, bone.getWorldPosition().toArray() );
+
+		var form = helper.multiplyTransforms( boneForm, boneOffsetForm );
+		var state = new Ammo.btDefaultMotionState( form );
+
+		var info = new Ammo.btRigidBodyConstructionInfo( weight, state, shape, localInertia );
+		info.set_m_friction( params.friction );
+		info.set_m_restitution( params.restitution );
+
+		var body = new Ammo.btRigidBody( info );
+
+		if ( params.type === 0 ) {
+
+			body.setCollisionFlags( body.getCollisionFlags() | 2 );
+
+			/*
+			 * It'd be better to comment out this line though in general I should call this method
+			 * because I'm not sure why but physics will be more like MMD's
+			 * if I comment out.
+			 */
+			body.setActivationState( 4 );
+
+		}
+
+		body.setDamping( params.positionDamping, params.rotationDamping );
+		body.setSleepingThresholds( 0, 0 );
+
+		this.world.addRigidBody( body, 1 << params.groupIndex, params.groupTarget );
+
+		this.body = body;
+		this.bone = bone;
+		this.boneOffsetForm = boneOffsetForm;
+		this.boneOffsetFormInverse = helper.inverseTransform( boneOffsetForm );
+
+		helper.freeVector3( localInertia );
+		helper.freeTransform( form );
+		helper.freeTransform( boneForm );
+
+	},
+
+	reset: function () {
+
+		this.setTransformFromBone();
+
+	},
+
+	updateFromBone: function () {
+
+		if ( this.params.boneIndex === -1 ) {
+
+			return;
+
+		}
+
+		if ( this.params.type === 0 ) {
+
+			this.setTransformFromBone();
+
+		}
+
+	},
+
+	updateBone: function () {
+
+		if ( this.params.type === 0 || this.params.boneIndex === -1 ) {
+
+			return;
+
+		}
+
+		this.updateBoneRotation();
+
+		if ( this.params.type === 1 ) {
+
+			this.updateBonePosition();
+
+		}
+
+		this.bone.updateMatrixWorld( true );
+
+		if ( this.params.type === 2 ) {
+
+			this.setPositionFromBone();
+
+		}
+
+	},
+
+	getBoneTransform: function () {
+
+		var helper = this.helper;
+		var p = this.bone.getWorldPosition();
+		var q = this.bone.getWorldQuaternion();
+
+		var tr = helper.allocTransform();
+		helper.setOriginFromArray3( tr, p.toArray() );
+		helper.setBasisFromArray4( tr, q.toArray() );
+
+		var form = helper.multiplyTransforms( tr, this.boneOffsetForm );
+
+		helper.freeTransform( tr );
+
+		return form;
+
+	},
+
+	getWorldTransformForBone: function () {
+
+		var helper = this.helper;
+
+		var tr = helper.allocTransform();
+		this.body.getMotionState().getWorldTransform( tr );
+		var tr2 = helper.multiplyTransforms( tr, this.boneOffsetFormInverse );
+
+		helper.freeTransform( tr );
+
+		return tr2;
+
+	},
+
+	setTransformFromBone: function () {
+
+		var helper = this.helper;
+		var form = this.getBoneTransform();
+
+		// TODO: check the most appropriate way to set
+		//this.body.setWorldTransform( form );
+		this.body.setCenterOfMassTransform( form );
+		this.body.getMotionState().setWorldTransform( form );
+
+		helper.freeTransform( form );
+
+	},
+
+	setPositionFromBone: function () {
+
+		var helper = this.helper;
+		var form = this.getBoneTransform();
+
+		var tr = helper.allocTransform();
+		this.body.getMotionState().getWorldTransform( tr );
+		helper.copyOrigin( tr, form );
+
+		// TODO: check the most appropriate way to set
+		//this.body.setWorldTransform( tr );
+		this.body.setCenterOfMassTransform( tr );
+		this.body.getMotionState().setWorldTransform( tr );
+
+		helper.freeTransform( tr );
+		helper.freeTransform( form );
+
+	},
+
+	updateBoneRotation: function () {
+
+		this.bone.updateMatrixWorld( true );
+
+		var helper = this.helper;
+
+		var tr = this.getWorldTransformForBone();
+		var q = helper.getBasis( tr );
+
+		var thQ = helper.allocThreeQuaternion();
+		var thQ2 = helper.allocThreeQuaternion();
+		var thQ3 = helper.allocThreeQuaternion();
+
+		thQ.set( q.x(), q.y(), q.z(), q.w() );
+		thQ2.setFromRotationMatrix( this.bone.matrixWorld );
+		thQ2.conjugate();
+		thQ2.multiply( thQ );
+
+		//this.bone.quaternion.multiply( thQ2 );
+
+		thQ3.setFromRotationMatrix( this.bone.matrix );
+		this.bone.quaternion.copy( thQ2.multiply( thQ3 ) );
+
+		helper.freeThreeQuaternion( thQ );
+		helper.freeThreeQuaternion( thQ2 );
+		helper.freeThreeQuaternion( thQ3 );
+
+		helper.freeQuaternion( q );
+		helper.freeTransform( tr );
+
+	},
+
+	updateBonePosition: function () {
+
+		var helper = this.helper;
+
+		var tr = this.getWorldTransformForBone();
+
+		var thV = helper.allocThreeVector3();
+
+		var o = helper.getOrigin( tr );
+		thV.set( o.x(), o.y(), o.z() );
+
+		var v = this.bone.worldToLocal( thV );
+		this.bone.position.add( v );
+
+		helper.freeThreeVector3( thV );
+
+		helper.freeTransform( tr );
+
+	}
+
+};
+
+THREE.MMDPhysics.Constraint = function ( mesh, world, bodyA, bodyB, params, helper ) {
+
+	this.mesh  = mesh;
+	this.world = world;
+	this.bodyA = bodyA;
+	this.bodyB = bodyB;
+	this.params = params;
+	this.helper = helper;
+
+	this.constraint = null;
+
+	this.init();
+
+};
+
+THREE.MMDPhysics.Constraint.prototype = {
+
+	constructor: THREE.MMDPhysics.Constraint,
+
+	init: function () {
+
+		var helper = this.helper;
+		var params = this.params;
+		var bodyA = this.bodyA;
+		var bodyB = this.bodyB;
+
+		var form = helper.allocTransform();
+		helper.setIdentity( form );
+		helper.setOriginFromArray3( form, params.position );
+		helper.setBasisFromArray3( form, params.rotation );
+
+		var formA = helper.allocTransform();
+		var formB = helper.allocTransform();
+
+		bodyA.body.getMotionState().getWorldTransform( formA );
+		bodyB.body.getMotionState().getWorldTransform( formB );
+
+		var formInverseA = helper.inverseTransform( formA );
+		var formInverseB = helper.inverseTransform( formB );
+
+		var formA2 = helper.multiplyTransforms( formInverseA, form );
+		var formB2 = helper.multiplyTransforms( formInverseB, form );
+
+		var constraint = new Ammo.btGeneric6DofSpringConstraint( bodyA.body, bodyB.body, formA2, formB2, true );
+
+		var lll = helper.allocVector3();
+		var lul = helper.allocVector3();
+		var all = helper.allocVector3();
+		var aul = helper.allocVector3();
+
+		lll.setValue( params.translationLimitation1[ 0 ],
+		              params.translationLimitation1[ 1 ],
+		              params.translationLimitation1[ 2 ] );
+		lul.setValue( params.translationLimitation2[ 0 ],
+		              params.translationLimitation2[ 1 ],
+		              params.translationLimitation2[ 2 ] );
+		all.setValue( params.rotationLimitation1[ 0 ],
+		              params.rotationLimitation1[ 1 ],
+		              params.rotationLimitation1[ 2 ] );
+		aul.setValue( params.rotationLimitation2[ 0 ],
+		              params.rotationLimitation2[ 1 ],
+		              params.rotationLimitation2[ 2 ] );
+
+		constraint.setLinearLowerLimit( lll );
+		constraint.setLinearUpperLimit( lul );
+		constraint.setAngularLowerLimit( all );
+		constraint.setAngularUpperLimit( aul );
+
+		for ( var i = 0; i < 3; i++ ) {
+
+			if( params.springPosition[ i ] !== 0 ) {
+
+				constraint.enableSpring( i, true );
+				constraint.setStiffness( i, params.springPosition[ i ] );
+
+			}
+
+		}
+
+		for ( var i = 0; i < 3; i++ ) {
+
+			if( params.springRotation[ i ] !== 0 ) {
+
+				constraint.enableSpring( i + 3, true );
+				constraint.setStiffness( i + 3, params.springRotation[ i ] );
+
+			}
+
+		}
+
+		/*
+		 * Currently(10/31/2016) official ammo.js doesn't support
+		 * btGeneric6DofSpringConstraint.setParam method.
+		 * You need custom ammo.js (add the method into idl) if you wanna use.
+		 * By setting this parameter, physics will be more like MMD's
+		 */
+		if ( constraint.setParam !== undefined ) {
+
+			for ( var i = 0; i < 6; i ++ ) {
+
+				// this parameter is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
+				constraint.setParam( 2, 0.475, i );
+
+			}
+
+		}
+
+		this.world.addConstraint( constraint, true );
+		this.constraint = constraint;
+
+		helper.freeTransform( form );
+		helper.freeTransform( formA );
+		helper.freeTransform( formB );
+		helper.freeTransform( formInverseA );
+		helper.freeTransform( formInverseB );
+		helper.freeTransform( formA2 );
+		helper.freeTransform( formB2 );
+		helper.freeVector3( lll );
+		helper.freeVector3( lul );
+		helper.freeVector3( all );
+		helper.freeVector3( aul );
+
+	}
+
+};
+
+
+THREE.MMDPhysicsHelper = function ( mesh ) {
+
+	if ( mesh.physics === undefined || mesh.geometry.rigidBodies === undefined ) {
+
+		throw 'THREE.MMDPhysicsHelper requires physics in mesh and rigidBodies in mesh.geometry.';
+
+	}
+
+	THREE.Object3D.call( this );
+
+	this.root = mesh;
+
+	this.matrix = mesh.matrixWorld;
+	this.matrixAutoUpdate = false;
+
+	this.materials = [];
+
+	this.materials.push(
+		new THREE.MeshBasicMaterial( {
+			color: new THREE.Color( 0xff8888 ),
+			wireframe: true,
+			depthTest: false,
+			depthWrite: false,
+			opacity: 0.25,
+			transparent: true
+		} )
+	);
+
+	this.materials.push(
+		new THREE.MeshBasicMaterial( {
+			color: new THREE.Color( 0x88ff88 ),
+			wireframe: true,
+			depthTest: false,
+			depthWrite: false,
+			opacity: 0.25,
+			transparent: true
+		} )
+	);
+
+	this.materials.push(
+		new THREE.MeshBasicMaterial( {
+			color: new THREE.Color( 0x8888ff ),
+			wireframe: true,
+			depthTest: false,
+			depthWrite: false,
+			opacity: 0.25,
+			transparent: true
+		} )
+	);
+
+	this._init();
+	this.update();
+
+};
+
+THREE.MMDPhysicsHelper.prototype = Object.create( THREE.Object3D.prototype );
+THREE.MMDPhysicsHelper.prototype.constructor = THREE.MMDPhysicsHelper;
+
+THREE.MMDPhysicsHelper.prototype._init = function () {
+
+	var mesh = this.root;
+	var rigidBodies = mesh.geometry.rigidBodies;
+
+	function createGeometry( param ) {
+
+		switch ( param.shapeType ) {
+
+			case 0:
+				return new THREE.SphereBufferGeometry( param.width, 16, 8 );
+
+			case 1:
+				return new THREE.BoxBufferGeometry( param.width * 2, param.height * 2, param.depth * 2, 8, 8, 8);
+
+			case 2:
+				return new createCapsuleGeometry( param.width, param.height, 16, 8 );
+
+			default:
+				return null;
+
+		}
+
+	}
+
+	// copy from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mytest37.js?ver=20160815
+	function createCapsuleGeometry( radius, cylinderHeight, segmentsRadius, segmentsHeight ) {
+
+		var geometry = new THREE.CylinderBufferGeometry( radius, radius, cylinderHeight, segmentsRadius, segmentsHeight, true );
+		var upperSphere = new THREE.Mesh( new THREE.SphereBufferGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, 0, Math.PI / 2 ) );
+		var lowerSphere = new THREE.Mesh( new THREE.SphereBufferGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, Math.PI / 2, Math.PI / 2 ) );
+
+		upperSphere.position.set( 0, cylinderHeight / 2, 0 );
+		lowerSphere.position.set( 0, -cylinderHeight / 2, 0 );
+
+		upperSphere.updateMatrix();
+		lowerSphere.updateMatrix();
+
+		geometry.merge( upperSphere.geometry, upperSphere.matrix );
+		geometry.merge( lowerSphere.geometry, lowerSphere.matrix );
+
+		return geometry;
+
+	}
+
+	for ( var i = 0, il = rigidBodies.length; i < il; i ++ ) {
+
+		var param = rigidBodies[ i ];
+		this.add( new THREE.Mesh( createGeometry( param ), this.materials[ param.type ] ) );
+
+	}
+
+};
+
+THREE.MMDPhysicsHelper.prototype.update = function () {
+
+	var mesh = this.root;
+	var rigidBodies = mesh.geometry.rigidBodies;
+	var bodies = mesh.physics.bodies;
+
+	var matrixWorldInv = new THREE.Matrix4().getInverse( mesh.matrixWorld );
+	var vector = new THREE.Vector3();
+	var quaternion = new THREE.Quaternion();
+	var quaternion2 = new THREE.Quaternion();
+
+	function getPosition( origin ) {
+
+		vector.set( origin.x(), origin.y(), origin.z() );
+		vector.applyMatrix4( matrixWorldInv );
+
+		return vector;
+
+	}
+
+	function getQuaternion( rotation ) {
+
+		quaternion.set( rotation.x(), rotation.y(), rotation.z(), rotation.w() );
+		quaternion2.setFromRotationMatrix( matrixWorldInv );
+		quaternion2.multiply( quaternion );
+
+		return quaternion2;
+
+	}
+
+	for ( var i = 0, il = rigidBodies.length; i < il; i ++ ) {
+
+		var body = bodies[ i ].body;
+		var mesh = this.children[ i ];
+
+		var tr = body.getCenterOfMassTransform();
+
+		mesh.position.copy( getPosition( tr.getOrigin() ) );
+		mesh.quaternion.copy( getQuaternion( tr.getRotation() ) );
+
+	}
+
+};

+ 188 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/cameras/CinematicCamera.js

@@ -0,0 +1,188 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author greggman / http://games.greggman.com/
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ * @author kaypiKun
+ */
+
+THREE.CinematicCamera = function( fov, aspect, near, far ) {
+
+	THREE.PerspectiveCamera.call( this, fov, aspect, near, far );
+
+	this.type = "CinematicCamera";
+
+	this.postprocessing = { enabled	: true };
+	this.shaderSettings = {
+		rings: 3,
+		samples: 4
+	};
+
+	this.material_depth = new THREE.MeshDepthMaterial();
+
+	// In case of cinematicCamera, having a default lens set is important
+	this.setLens();
+
+	this.initPostProcessing();
+
+};
+
+THREE.CinematicCamera.prototype = Object.create( THREE.PerspectiveCamera.prototype );
+THREE.CinematicCamera.prototype.constructor = THREE.CinematicCamera;
+
+
+// providing fnumber and coc(Circle of Confusion) as extra arguments
+THREE.CinematicCamera.prototype.setLens = function ( focalLength, filmGauge, fNumber, coc ) {
+
+	// In case of cinematicCamera, having a default lens set is important
+	if ( focalLength === undefined ) focalLength = 35;
+	if ( filmGauge !== undefined ) this.filmGauge = filmGauge;
+
+	this.setFocalLength( focalLength );
+
+	// if fnumber and coc are not provided, cinematicCamera tries to act as a basic PerspectiveCamera
+	if ( fNumber === undefined ) fNumber = 8;
+	if ( coc === undefined ) coc = 0.019;
+
+	this.fNumber = fNumber;
+	this.coc = coc;
+
+	// fNumber is focalLength by aperture
+	this.aperture = focalLength / this.fNumber;
+
+	// hyperFocal is required to calculate depthOfField when a lens tries to focus at a distance with given fNumber and focalLength
+	this.hyperFocal = ( focalLength * focalLength ) / ( this.aperture * this.coc );
+
+};
+
+THREE.CinematicCamera.prototype.linearize = function ( depth ) {
+
+	var zfar = this.far;
+	var znear = this.near;
+	return - zfar * znear / ( depth * ( zfar - znear ) - zfar );
+
+};
+
+THREE.CinematicCamera.prototype.smoothstep = function ( near, far, depth ) {
+
+	var x = this.saturate( ( depth - near ) / ( far - near ) );
+	return x * x * ( 3 - 2 * x );
+
+};
+
+THREE.CinematicCamera.prototype.saturate = function ( x ) {
+
+	return Math.max( 0, Math.min( 1, x ) );
+
+};
+
+// function for focusing at a distance from the camera
+THREE.CinematicCamera.prototype.focusAt = function ( focusDistance ) {
+
+	if ( focusDistance === undefined ) focusDistance = 20;
+
+	var focalLength = this.getFocalLength();
+
+	// distance from the camera (normal to frustrum) to focus on
+	this.focus = focusDistance;
+
+	// the nearest point from the camera which is in focus (unused)
+	this.nearPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal + ( this.focus - focalLength ) );
+
+	// the farthest point from the camera which is in focus (unused)
+	this.farPoint = ( this.hyperFocal * this.focus ) / ( this.hyperFocal - ( this.focus - focalLength ) );
+
+	// the gap or width of the space in which is everything is in focus (unused)
+	this.depthOfField = this.farPoint - this.nearPoint;
+
+	// Considering minimum distance of focus for a standard lens (unused)
+	if ( this.depthOfField < 0 ) this.depthOfField = 0;
+
+	this.sdistance = this.smoothstep( this.near, this.far, this.focus );
+
+	this.ldistance = this.linearize( 1 -	this.sdistance );
+
+	this.postprocessing.bokeh_uniforms[ 'focalDepth' ].value = this.ldistance;
+
+};
+
+THREE.CinematicCamera.prototype.initPostProcessing = function () {
+
+	if ( this.postprocessing.enabled ) {
+
+		this.postprocessing.scene = new THREE.Scene();
+
+		this.postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2,	window.innerHeight / 2, window.innerHeight / - 2, - 10000, 10000 );
+
+		this.postprocessing.scene.add( this.postprocessing.camera );
+
+		var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
+		this.postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
+		this.postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, pars );
+
+		var bokeh_shader = THREE.BokehShader;
+
+		this.postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms );
+
+		this.postprocessing.bokeh_uniforms[ "tColor" ].value = this.postprocessing.rtTextureColor.texture;
+		this.postprocessing.bokeh_uniforms[ "tDepth" ].value = this.postprocessing.rtTextureDepth.texture;
+
+		this.postprocessing.bokeh_uniforms[ "manualdof" ].value = 0;
+		this.postprocessing.bokeh_uniforms[ "shaderFocus" ].value = 0;
+
+		this.postprocessing.bokeh_uniforms[ "fstop" ].value = 2.8;
+
+		this.postprocessing.bokeh_uniforms[ "showFocus" ].value = 1;
+
+		this.postprocessing.bokeh_uniforms[ "focalDepth" ].value = 0.1;
+
+		//console.log( this.postprocessing.bokeh_uniforms[ "focalDepth" ].value );
+
+		this.postprocessing.bokeh_uniforms[ "znear" ].value = this.near;
+		this.postprocessing.bokeh_uniforms[ "zfar" ].value = this.near;
+
+
+		this.postprocessing.bokeh_uniforms[ "textureWidth" ].value = window.innerWidth;
+
+		this.postprocessing.bokeh_uniforms[ "textureHeight" ].value = window.innerHeight;
+
+		this.postprocessing.materialBokeh = new THREE.ShaderMaterial( {
+			uniforms: this.postprocessing.bokeh_uniforms,
+			vertexShader: bokeh_shader.vertexShader,
+			fragmentShader: bokeh_shader.fragmentShader,
+			defines: {
+				RINGS: this.shaderSettings.rings,
+				SAMPLES: this.shaderSettings.samples
+			}
+		} );
+
+		this.postprocessing.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight ), this.postprocessing.materialBokeh );
+		this.postprocessing.quad.position.z = - 500;
+		this.postprocessing.scene.add( this.postprocessing.quad );
+
+	}
+
+};
+
+THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
+
+	if ( this.postprocessing.enabled ) {
+
+		renderer.clear();
+
+		// Render scene into texture
+
+		scene.overrideMaterial = null;
+		renderer.render( scene, camera, this.postprocessing.rtTextureColor, true );
+
+		// Render depth into texture
+
+		scene.overrideMaterial = this.material_depth;
+		renderer.render( scene, camera, this.postprocessing.rtTextureDepth, true );
+
+		// Render bokeh composite
+
+		renderer.render( this.postprocessing.scene, this.postprocessing.camera );
+
+	}
+
+};

+ 230 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/cameras/CombinedCamera.js

@@ -0,0 +1,230 @@
+/**
+ *	@author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
+ *
+ *	A general perpose camera, for setting FOV, Lens Focal Length,
+ *		and switching between perspective and orthographic views easily.
+ *		Use this only if you do not wish to manage
+ *		both a Orthographic and Perspective Camera
+ *
+ */
+
+
+THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
+
+	THREE.Camera.call( this );
+
+	this.fov = fov;
+
+	this.left = - width / 2;
+	this.right = width / 2;
+	this.top = height / 2;
+	this.bottom = - height / 2;
+
+	// We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
+
+	this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 	orthoNear, orthoFar );
+	this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
+
+	this.zoom = 1;
+
+	this.toPerspective();
+
+};
+
+THREE.CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
+THREE.CombinedCamera.prototype.constructor = THREE.CombinedCamera;
+
+THREE.CombinedCamera.prototype.toPerspective = function () {
+
+	// Switches to the Perspective Camera
+
+	this.near = this.cameraP.near;
+	this.far = this.cameraP.far;
+
+	this.cameraP.fov =  this.fov / this.zoom ;
+
+	this.cameraP.updateProjectionMatrix();
+
+	this.projectionMatrix = this.cameraP.projectionMatrix;
+
+	this.inPerspectiveMode = true;
+	this.inOrthographicMode = false;
+
+};
+
+THREE.CombinedCamera.prototype.toOrthographic = function () {
+
+	// Switches to the Orthographic camera estimating viewport from Perspective
+
+	var fov = this.fov;
+	var aspect = this.cameraP.aspect;
+	var near = this.cameraP.near;
+	var far = this.cameraP.far;
+
+	// The size that we set is the mid plane of the viewing frustum
+
+	var hyperfocus = ( near + far ) / 2;
+
+	var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * hyperfocus;
+	var halfWidth = halfHeight * aspect;
+
+	halfHeight /= this.zoom;
+	halfWidth /= this.zoom;
+
+	this.cameraO.left = - halfWidth;
+	this.cameraO.right = halfWidth;
+	this.cameraO.top = halfHeight;
+	this.cameraO.bottom = - halfHeight;
+
+	// this.cameraO.left = -farHalfWidth;
+	// this.cameraO.right = farHalfWidth;
+	// this.cameraO.top = farHalfHeight;
+	// this.cameraO.bottom = -farHalfHeight;
+
+	// this.cameraO.left = this.left / this.zoom;
+	// this.cameraO.right = this.right / this.zoom;
+	// this.cameraO.top = this.top / this.zoom;
+	// this.cameraO.bottom = this.bottom / this.zoom;
+
+	this.cameraO.updateProjectionMatrix();
+
+	this.near = this.cameraO.near;
+	this.far = this.cameraO.far;
+	this.projectionMatrix = this.cameraO.projectionMatrix;
+
+	this.inPerspectiveMode = false;
+	this.inOrthographicMode = true;
+
+};
+
+
+THREE.CombinedCamera.prototype.setSize = function( width, height ) {
+
+	this.cameraP.aspect = width / height;
+	this.left = - width / 2;
+	this.right = width / 2;
+	this.top = height / 2;
+	this.bottom = - height / 2;
+
+};
+
+
+THREE.CombinedCamera.prototype.setFov = function( fov ) {
+
+	this.fov = fov;
+
+	if ( this.inPerspectiveMode ) {
+
+		this.toPerspective();
+
+	} else {
+
+		this.toOrthographic();
+
+	}
+
+};
+
+// For maintaining similar API with PerspectiveCamera
+
+THREE.CombinedCamera.prototype.updateProjectionMatrix = function() {
+
+	if ( this.inPerspectiveMode ) {
+
+		this.toPerspective();
+
+	} else {
+
+		this.toPerspective();
+		this.toOrthographic();
+
+	}
+
+};
+
+/*
+* Uses Focal Length (in mm) to estimate and set FOV
+* 35mm (full frame) camera is used if frame size is not specified;
+* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
+*/
+THREE.CombinedCamera.prototype.setLens = function ( focalLength, filmGauge ) {
+
+	if ( filmGauge === undefined ) filmGauge = 35;
+
+	var vExtentSlope = 0.5 * filmGauge /
+			( focalLength * Math.max( this.cameraP.aspect, 1 ) );
+
+	var fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
+
+	this.setFov( fov );
+
+	return fov;
+
+};
+
+
+THREE.CombinedCamera.prototype.setZoom = function( zoom ) {
+
+	this.zoom = zoom;
+
+	if ( this.inPerspectiveMode ) {
+
+		this.toPerspective();
+
+	} else {
+
+		this.toOrthographic();
+
+	}
+
+};
+
+THREE.CombinedCamera.prototype.toFrontView = function() {
+
+	this.rotation.x = 0;
+	this.rotation.y = 0;
+	this.rotation.z = 0;
+
+	// should we be modifing the matrix instead?
+
+};
+
+THREE.CombinedCamera.prototype.toBackView = function() {
+
+	this.rotation.x = 0;
+	this.rotation.y = Math.PI;
+	this.rotation.z = 0;
+
+};
+
+THREE.CombinedCamera.prototype.toLeftView = function() {
+
+	this.rotation.x = 0;
+	this.rotation.y = - Math.PI / 2;
+	this.rotation.z = 0;
+
+};
+
+THREE.CombinedCamera.prototype.toRightView = function() {
+
+	this.rotation.x = 0;
+	this.rotation.y = Math.PI / 2;
+	this.rotation.z = 0;
+
+};
+
+THREE.CombinedCamera.prototype.toTopView = function() {
+
+	this.rotation.x = - Math.PI / 2;
+	this.rotation.y = 0;
+	this.rotation.z = 0;
+
+};
+
+THREE.CombinedCamera.prototype.toBottomView = function() {
+
+	this.rotation.x = Math.PI / 2;
+	this.rotation.y = 0;
+	this.rotation.z = 0;
+
+};

+ 111 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/DeviceOrientationControls.js

@@ -0,0 +1,111 @@
+/**
+ * @author richt / http://richt.me
+ * @author WestLangley / http://github.com/WestLangley
+ *
+ * W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html)
+ */
+
+THREE.DeviceOrientationControls = function( object ) {
+
+	var scope = this;
+
+	this.object = object;
+	this.object.rotation.reorder( "YXZ" );
+
+	this.enabled = true;
+
+	this.deviceOrientation = {};
+	this.screenOrientation = 0;
+
+	this.alpha = 0;
+	this.alphaOffsetAngle = 0;
+
+
+	var onDeviceOrientationChangeEvent = function( event ) {
+
+		scope.deviceOrientation = event;
+
+	};
+
+	var onScreenOrientationChangeEvent = function() {
+
+		scope.screenOrientation = window.orientation || 0;
+
+	};
+
+	// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
+
+	var setObjectQuaternion = function() {
+
+		var zee = new THREE.Vector3( 0, 0, 1 );
+
+		var euler = new THREE.Euler();
+
+		var q0 = new THREE.Quaternion();
+
+		var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
+
+		return function( quaternion, alpha, beta, gamma, orient ) {
+
+			euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us
+
+			quaternion.setFromEuler( euler ); // orient the device
+
+			quaternion.multiply( q1 ); // camera looks out the back of the device, not the top
+
+			quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation
+
+		}
+
+	}();
+
+	this.connect = function() {
+
+		onScreenOrientationChangeEvent(); // run once on load
+
+		window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+		window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
+
+		scope.enabled = true;
+
+	};
+
+	this.disconnect = function() {
+
+		window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+		window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
+
+		scope.enabled = false;
+
+	};
+
+	this.update = function() {
+
+		if ( scope.enabled === false ) return;
+
+		var alpha = scope.deviceOrientation.alpha ? THREE.Math.degToRad( scope.deviceOrientation.alpha ) + this.alphaOffsetAngle : 0; // Z
+		var beta = scope.deviceOrientation.beta ? THREE.Math.degToRad( scope.deviceOrientation.beta ) : 0; // X'
+		var gamma = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.gamma ) : 0; // Y''
+		var orient = scope.screenOrientation ? THREE.Math.degToRad( scope.screenOrientation ) : 0; // O
+
+		setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient );
+		this.alpha = alpha;
+
+	};
+
+	this.updateAlphaOffsetAngle = function( angle ) {
+
+		this.alphaOffsetAngle = angle;
+		this.update();
+
+	};
+
+	this.dispose = function() {
+
+		this.disconnect();
+
+	};
+
+	this.connect();
+
+};

+ 193 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/DragControls.js

@@ -0,0 +1,193 @@
+/*
+ * @author zz85 / https://github.com/zz85
+ * @author mrdoob / http://mrdoob.com
+ * Running this will allow you to drag three.js objects around the screen.
+ */
+
+THREE.DragControls = function ( _objects, _camera, _domElement ) {
+
+	if ( _objects instanceof THREE.Camera ) {
+
+		console.warn( 'THREE.DragControls: Constructor now expects ( objects, camera, domElement )' );
+		var temp = _objects; _objects = _camera; _camera = temp;
+
+	}
+
+	var _plane = new THREE.Plane();
+	var _raycaster = new THREE.Raycaster();
+
+	var _mouse = new THREE.Vector2();
+	var _offset = new THREE.Vector3();
+	var _intersection = new THREE.Vector3();
+
+	var _selected = null, _hovered = null;
+
+	//
+
+	var scope = this;
+
+	function activate() {
+
+		_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
+		_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
+		_domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
+
+	}
+
+	function deactivate() {
+
+		_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+		_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
+		_domElement.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+
+	}
+
+	function dispose() {
+
+		deactivate();
+
+	}
+
+	function onDocumentMouseMove( event ) {
+
+		event.preventDefault();
+
+		_mouse.x = ( event.clientX / _domElement.width ) * 2 - 1;
+		_mouse.y = - ( event.clientY / _domElement.height ) * 2 + 1;
+
+		_raycaster.setFromCamera( _mouse, _camera );
+
+		if ( _selected && scope.enabled ) {
+
+			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
+
+				_selected.position.copy( _intersection.sub( _offset ) );
+
+			}
+
+			scope.dispatchEvent( { type: 'drag', object: _selected } );
+
+			return;
+
+		}
+
+		_raycaster.setFromCamera( _mouse, _camera );
+
+		var intersects = _raycaster.intersectObjects( _objects );
+
+		if ( intersects.length > 0 ) {
+
+			var object = intersects[ 0 ].object;
+
+			_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), object.position );
+
+			if ( _hovered !== object ) {
+
+				scope.dispatchEvent( { type: 'hoveron', object: object } );
+
+				_domElement.style.cursor = 'pointer';
+				_hovered = object;
+
+			}
+
+		} else {
+
+			if ( _hovered !== null ) {
+
+				scope.dispatchEvent( { type: 'hoveroff', object: _hovered } );
+
+				_domElement.style.cursor = 'auto';
+				_hovered = null;
+
+			}
+
+		}
+
+	}
+
+	function onDocumentMouseDown( event ) {
+
+		event.preventDefault();
+
+		_raycaster.setFromCamera( _mouse, _camera );
+
+		var intersects = _raycaster.intersectObjects( _objects );
+
+		if ( intersects.length > 0 ) {
+
+			_selected = intersects[ 0 ].object;
+
+			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
+
+				_offset.copy( _intersection ).sub( _selected.position );
+
+			}
+
+			_domElement.style.cursor = 'move';
+
+			scope.dispatchEvent( { type: 'dragstart', object: _selected } );
+
+		}
+
+
+	}
+
+	function onDocumentMouseUp( event ) {
+
+		event.preventDefault();
+
+		if ( _selected ) {
+
+			scope.dispatchEvent( { type: 'dragend', object: _selected } );
+
+			_selected = null;
+
+		}
+
+		_domElement.style.cursor = 'auto';
+
+	}
+
+	activate();
+
+	// API
+
+	this.enabled = true;
+
+	this.activate = activate;
+	this.deactivate = deactivate;
+	this.dispose = dispose;
+
+	// Backward compatibility
+
+	this.setObjects = function () {
+
+		console.error( 'THREE.DragControls: setObjects() has been removed.' );
+
+	};
+
+	this.on = function ( type, listener ) {
+
+		console.warn( 'THREE.DragControls: on() has been deprecated. Use addEventListener() instead.' );
+		scope.addEventListener( type, listener );
+
+	};
+
+	this.off = function ( type, listener ) {
+
+		console.warn( 'THREE.DragControls: off() has been deprecated. Use removeEventListener() instead.' );
+		scope.removeEventListener( type, listener );
+
+	};
+
+	this.notify = function ( type ) {
+
+		console.error( 'THREE.DragControls: notify() has been deprecated. Use dispatchEvent() instead.' );
+		scope.dispatchEvent( { type: type } );
+
+	};
+
+};
+
+THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.DragControls.prototype.constructor = THREE.DragControls;

+ 293 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/EditorControls.js

@@ -0,0 +1,293 @@
+/**
+ * @author qiao / https://github.com/qiao
+ * @author mrdoob / http://mrdoob.com
+ * @author alteredq / http://alteredqualia.com/
+ * @author WestLangley / http://github.com/WestLangley
+ */
+
+THREE.EditorControls = function ( object, domElement ) {
+
+	domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// API
+
+	this.enabled = true;
+	this.center = new THREE.Vector3();
+	this.panSpeed = 0.001;
+	this.zoomSpeed = 0.001;
+	this.rotationSpeed = 0.005;
+
+	// internals
+
+	var scope = this;
+	var vector = new THREE.Vector3();
+
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2 };
+	var state = STATE.NONE;
+
+	var center = this.center;
+	var normalMatrix = new THREE.Matrix3();
+	var pointer = new THREE.Vector2();
+	var pointerOld = new THREE.Vector2();
+	var spherical = new THREE.Spherical();
+
+	// events
+
+	var changeEvent = { type: 'change' };
+
+	this.focus = function ( target ) {
+
+		var box = new THREE.Box3().setFromObject( target );
+		object.lookAt( center.copy( box.getCenter() ) );
+		scope.dispatchEvent( changeEvent );
+
+	};
+
+	this.pan = function ( delta ) {
+
+		var distance = object.position.distanceTo( center );
+
+		delta.multiplyScalar( distance * scope.panSpeed );
+		delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) );
+
+		object.position.add( delta );
+		center.add( delta );
+
+		scope.dispatchEvent( changeEvent );
+
+	};
+
+	this.zoom = function ( delta ) {
+
+		var distance = object.position.distanceTo( center );
+
+		delta.multiplyScalar( distance * scope.zoomSpeed );
+
+		if ( delta.length() > distance ) return;
+
+		delta.applyMatrix3( normalMatrix.getNormalMatrix( object.matrix ) );
+
+		object.position.add( delta );
+
+		scope.dispatchEvent( changeEvent );
+
+	};
+
+	this.rotate = function ( delta ) {
+
+		vector.copy( object.position ).sub( center );
+
+		spherical.setFromVector3( vector );
+
+		spherical.theta += delta.x;
+		spherical.phi += delta.y;
+
+		spherical.makeSafe();
+
+		vector.setFromSpherical( spherical );
+
+		object.position.copy( center ).add( vector );
+
+		object.lookAt( center );
+
+		scope.dispatchEvent( changeEvent );
+
+	};
+
+	// mouse
+
+	function onMouseDown( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		if ( event.button === 0 ) {
+
+			state = STATE.ROTATE;
+
+		} else if ( event.button === 1 ) {
+
+			state = STATE.ZOOM;
+
+		} else if ( event.button === 2 ) {
+
+			state = STATE.PAN;
+
+		}
+
+		pointerOld.set( event.clientX, event.clientY );
+
+		domElement.addEventListener( 'mousemove', onMouseMove, false );
+		domElement.addEventListener( 'mouseup', onMouseUp, false );
+		domElement.addEventListener( 'mouseout', onMouseUp, false );
+		domElement.addEventListener( 'dblclick', onMouseUp, false );
+
+	}
+
+	function onMouseMove( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		pointer.set( event.clientX, event.clientY );
+
+		var movementX = pointer.x - pointerOld.x;
+		var movementY = pointer.y - pointerOld.y;
+
+		if ( state === STATE.ROTATE ) {
+
+			scope.rotate( new THREE.Vector3( - movementX * scope.rotationSpeed, - movementY * scope.rotationSpeed, 0 ) );
+
+		} else if ( state === STATE.ZOOM ) {
+
+			scope.zoom( new THREE.Vector3( 0, 0, movementY ) );
+
+		} else if ( state === STATE.PAN ) {
+
+			scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
+
+		}
+
+		pointerOld.set( event.clientX, event.clientY );
+
+	}
+
+	function onMouseUp( event ) {
+
+		domElement.removeEventListener( 'mousemove', onMouseMove, false );
+		domElement.removeEventListener( 'mouseup', onMouseUp, false );
+		domElement.removeEventListener( 'mouseout', onMouseUp, false );
+		domElement.removeEventListener( 'dblclick', onMouseUp, false );
+
+		state = STATE.NONE;
+
+	}
+
+	function onMouseWheel( event ) {
+
+		event.preventDefault();
+
+		// if ( scope.enabled === false ) return;
+
+		scope.zoom( new THREE.Vector3( 0, 0, event.deltaY ) );
+
+	}
+
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		domElement.removeEventListener( 'mousedown', onMouseDown, false );
+		domElement.removeEventListener( 'wheel', onMouseWheel, false );
+
+		domElement.removeEventListener( 'mousemove', onMouseMove, false );
+		domElement.removeEventListener( 'mouseup', onMouseUp, false );
+		domElement.removeEventListener( 'mouseout', onMouseUp, false );
+		domElement.removeEventListener( 'dblclick', onMouseUp, false );
+
+		domElement.removeEventListener( 'touchstart', touchStart, false );
+		domElement.removeEventListener( 'touchmove', touchMove, false );
+
+	};
+
+	domElement.addEventListener( 'contextmenu', contextmenu, false );
+	domElement.addEventListener( 'mousedown', onMouseDown, false );
+	domElement.addEventListener( 'wheel', onMouseWheel, false );
+
+	// touch
+
+	var touch = new THREE.Vector3();
+
+	var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+
+	var prevDistance = null;
+
+	function touchStart( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				break;
+
+			case 2:
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
+				break;
+
+		}
+
+		prevTouches[ 0 ].copy( touches[ 0 ] );
+		prevTouches[ 1 ].copy( touches[ 1 ] );
+
+	}
+
+
+	function touchMove( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		function getClosest( touch, touches ) {
+
+			var closest = touches[ 0 ];
+
+			for ( var i in touches ) {
+
+				if ( closest.distanceTo( touch ) > touches[ i ].distanceTo( touch ) ) closest = touches[ i ];
+
+			}
+
+			return closest;
+
+		}
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - scope.rotationSpeed ) );
+				break;
+
+			case 2:
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				distance = touches[ 0 ].distanceTo( touches[ 1 ] );
+				scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) );
+				prevDistance = distance;
+
+
+				var offset0 = touches[ 0 ].clone().sub( getClosest( touches[ 0 ], prevTouches ) );
+				var offset1 = touches[ 1 ].clone().sub( getClosest( touches[ 1 ], prevTouches ) );
+				offset0.x = - offset0.x;
+				offset1.x = - offset1.x;
+
+				scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) );
+
+				break;
+
+		}
+
+		prevTouches[ 0 ].copy( touches[ 0 ] );
+		prevTouches[ 1 ].copy( touches[ 1 ] );
+
+	}
+
+	domElement.addEventListener( 'touchstart', touchStart, false );
+	domElement.addEventListener( 'touchmove', touchMove, false );
+
+};
+
+THREE.EditorControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.EditorControls.prototype.constructor = THREE.EditorControls;

+ 300 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/FirstPersonControls.js

@@ -0,0 +1,300 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author paulirish / http://paulirish.com/
+ */
+
+THREE.FirstPersonControls = function ( object, domElement ) {
+
+	this.object = object;
+	this.target = new THREE.Vector3( 0, 0, 0 );
+
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	this.enabled = true;
+
+	this.movementSpeed = 1.0;
+	this.lookSpeed = 0.005;
+
+	this.lookVertical = true;
+	this.autoForward = false;
+
+	this.activeLook = true;
+
+	this.heightSpeed = false;
+	this.heightCoef = 1.0;
+	this.heightMin = 0.0;
+	this.heightMax = 1.0;
+
+	this.constrainVertical = false;
+	this.verticalMin = 0;
+	this.verticalMax = Math.PI;
+
+	this.autoSpeedFactor = 0.0;
+
+	this.mouseX = 0;
+	this.mouseY = 0;
+
+	this.lat = 0;
+	this.lon = 0;
+	this.phi = 0;
+	this.theta = 0;
+
+	this.moveForward = false;
+	this.moveBackward = false;
+	this.moveLeft = false;
+	this.moveRight = false;
+
+	this.mouseDragOn = false;
+
+	this.viewHalfX = 0;
+	this.viewHalfY = 0;
+
+	if ( this.domElement !== document ) {
+
+		this.domElement.setAttribute( 'tabindex', - 1 );
+
+	}
+
+	//
+
+	this.handleResize = function () {
+
+		if ( this.domElement === document ) {
+
+			this.viewHalfX = window.innerWidth / 2;
+			this.viewHalfY = window.innerHeight / 2;
+
+		} else {
+
+			this.viewHalfX = this.domElement.offsetWidth / 2;
+			this.viewHalfY = this.domElement.offsetHeight / 2;
+
+		}
+
+	};
+
+	this.onMouseDown = function ( event ) {
+
+		if ( this.domElement !== document ) {
+
+			this.domElement.focus();
+
+		}
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( this.activeLook ) {
+
+			switch ( event.button ) {
+
+				case 0: this.moveForward = true; break;
+				case 2: this.moveBackward = true; break;
+
+			}
+
+		}
+
+		this.mouseDragOn = true;
+
+	};
+
+	this.onMouseUp = function ( event ) {
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( this.activeLook ) {
+
+			switch ( event.button ) {
+
+				case 0: this.moveForward = false; break;
+				case 2: this.moveBackward = false; break;
+
+			}
+
+		}
+
+		this.mouseDragOn = false;
+
+	};
+
+	this.onMouseMove = function ( event ) {
+
+		if ( this.domElement === document ) {
+
+			this.mouseX = event.pageX - this.viewHalfX;
+			this.mouseY = event.pageY - this.viewHalfY;
+
+		} else {
+
+			this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
+			this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
+
+		}
+
+	};
+
+	this.onKeyDown = function ( event ) {
+
+		//event.preventDefault();
+
+		switch ( event.keyCode ) {
+
+			case 38: /*up*/
+			case 87: /*W*/ this.moveForward = true; break;
+
+			case 37: /*left*/
+			case 65: /*A*/ this.moveLeft = true; break;
+
+			case 40: /*down*/
+			case 83: /*S*/ this.moveBackward = true; break;
+
+			case 39: /*right*/
+			case 68: /*D*/ this.moveRight = true; break;
+
+			case 82: /*R*/ this.moveUp = true; break;
+			case 70: /*F*/ this.moveDown = true; break;
+
+		}
+
+	};
+
+	this.onKeyUp = function ( event ) {
+
+		switch ( event.keyCode ) {
+
+			case 38: /*up*/
+			case 87: /*W*/ this.moveForward = false; break;
+
+			case 37: /*left*/
+			case 65: /*A*/ this.moveLeft = false; break;
+
+			case 40: /*down*/
+			case 83: /*S*/ this.moveBackward = false; break;
+
+			case 39: /*right*/
+			case 68: /*D*/ this.moveRight = false; break;
+
+			case 82: /*R*/ this.moveUp = false; break;
+			case 70: /*F*/ this.moveDown = false; break;
+
+		}
+
+	};
+
+	this.update = function( delta ) {
+
+		if ( this.enabled === false ) return;
+
+		if ( this.heightSpeed ) {
+
+			var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
+			var heightDelta = y - this.heightMin;
+
+			this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
+
+		} else {
+
+			this.autoSpeedFactor = 0.0;
+
+		}
+
+		var actualMoveSpeed = delta * this.movementSpeed;
+
+		if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
+		if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
+
+		if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
+		if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
+
+		if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
+		if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
+
+		var actualLookSpeed = delta * this.lookSpeed;
+
+		if ( ! this.activeLook ) {
+
+			actualLookSpeed = 0;
+
+		}
+
+		var verticalLookRatio = 1;
+
+		if ( this.constrainVertical ) {
+
+			verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
+
+		}
+
+		this.lon += this.mouseX * actualLookSpeed;
+		if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
+
+		this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
+		this.phi = THREE.Math.degToRad( 90 - this.lat );
+
+		this.theta = THREE.Math.degToRad( this.lon );
+
+		if ( this.constrainVertical ) {
+
+			this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
+
+		}
+
+		var targetPosition = this.target,
+			position = this.object.position;
+
+		targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
+		targetPosition.y = position.y + 100 * Math.cos( this.phi );
+		targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
+
+		this.object.lookAt( targetPosition );
+
+	};
+
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _onMouseDown, false );
+		this.domElement.removeEventListener( 'mousemove', _onMouseMove, false );
+		this.domElement.removeEventListener( 'mouseup', _onMouseUp, false );
+
+		window.removeEventListener( 'keydown', _onKeyDown, false );
+		window.removeEventListener( 'keyup', _onKeyUp, false );
+
+	};
+
+	var _onMouseMove = bind( this, this.onMouseMove );
+	var _onMouseDown = bind( this, this.onMouseDown );
+	var _onMouseUp = bind( this, this.onMouseUp );
+	var _onKeyDown = bind( this, this.onKeyDown );
+	var _onKeyUp = bind( this, this.onKeyUp );
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousemove', _onMouseMove, false );
+	this.domElement.addEventListener( 'mousedown', _onMouseDown, false );
+	this.domElement.addEventListener( 'mouseup', _onMouseUp, false );
+
+	window.addEventListener( 'keydown', _onKeyDown, false );
+	window.addEventListener( 'keyup', _onKeyUp, false );
+
+	function bind( scope, fn ) {
+
+		return function () {
+
+			fn.apply( scope, arguments );
+
+		};
+
+	}
+
+	this.handleResize();
+
+};

+ 293 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/FlyControls.js

@@ -0,0 +1,293 @@
+/**
+ * @author James Baicoianu / http://www.baicoianu.com/
+ */
+
+THREE.FlyControls = function ( object, domElement ) {
+
+	this.object = object;
+
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+	if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 );
+
+	// API
+
+	this.movementSpeed = 1.0;
+	this.rollSpeed = 0.005;
+
+	this.dragToLook = false;
+	this.autoForward = false;
+
+	// disable default target object behavior
+
+	// internals
+
+	this.tmpQuaternion = new THREE.Quaternion();
+
+	this.mouseStatus = 0;
+
+	this.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 };
+	this.moveVector = new THREE.Vector3( 0, 0, 0 );
+	this.rotationVector = new THREE.Vector3( 0, 0, 0 );
+
+	this.handleEvent = function ( event ) {
+
+		if ( typeof this[ event.type ] == 'function' ) {
+
+			this[ event.type ]( event );
+
+		}
+
+	};
+
+	this.keydown = function( event ) {
+
+		if ( event.altKey ) {
+
+			return;
+
+		}
+
+		//event.preventDefault();
+
+		switch ( event.keyCode ) {
+
+			case 16: /* shift */ this.movementSpeedMultiplier = .1; break;
+
+			case 87: /*W*/ this.moveState.forward = 1; break;
+			case 83: /*S*/ this.moveState.back = 1; break;
+
+			case 65: /*A*/ this.moveState.left = 1; break;
+			case 68: /*D*/ this.moveState.right = 1; break;
+
+			case 82: /*R*/ this.moveState.up = 1; break;
+			case 70: /*F*/ this.moveState.down = 1; break;
+
+			case 38: /*up*/ this.moveState.pitchUp = 1; break;
+			case 40: /*down*/ this.moveState.pitchDown = 1; break;
+
+			case 37: /*left*/ this.moveState.yawLeft = 1; break;
+			case 39: /*right*/ this.moveState.yawRight = 1; break;
+
+			case 81: /*Q*/ this.moveState.rollLeft = 1; break;
+			case 69: /*E*/ this.moveState.rollRight = 1; break;
+
+		}
+
+		this.updateMovementVector();
+		this.updateRotationVector();
+
+	};
+
+	this.keyup = function( event ) {
+
+		switch ( event.keyCode ) {
+
+			case 16: /* shift */ this.movementSpeedMultiplier = 1; break;
+
+			case 87: /*W*/ this.moveState.forward = 0; break;
+			case 83: /*S*/ this.moveState.back = 0; break;
+
+			case 65: /*A*/ this.moveState.left = 0; break;
+			case 68: /*D*/ this.moveState.right = 0; break;
+
+			case 82: /*R*/ this.moveState.up = 0; break;
+			case 70: /*F*/ this.moveState.down = 0; break;
+
+			case 38: /*up*/ this.moveState.pitchUp = 0; break;
+			case 40: /*down*/ this.moveState.pitchDown = 0; break;
+
+			case 37: /*left*/ this.moveState.yawLeft = 0; break;
+			case 39: /*right*/ this.moveState.yawRight = 0; break;
+
+			case 81: /*Q*/ this.moveState.rollLeft = 0; break;
+			case 69: /*E*/ this.moveState.rollRight = 0; break;
+
+		}
+
+		this.updateMovementVector();
+		this.updateRotationVector();
+
+	};
+
+	this.mousedown = function( event ) {
+
+		if ( this.domElement !== document ) {
+
+			this.domElement.focus();
+
+		}
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( this.dragToLook ) {
+
+			this.mouseStatus ++;
+
+		} else {
+
+			switch ( event.button ) {
+
+				case 0: this.moveState.forward = 1; break;
+				case 2: this.moveState.back = 1; break;
+
+			}
+
+			this.updateMovementVector();
+
+		}
+
+	};
+
+	this.mousemove = function( event ) {
+
+		if ( ! this.dragToLook || this.mouseStatus > 0 ) {
+
+			var container = this.getContainerDimensions();
+			var halfWidth  = container.size[ 0 ] / 2;
+			var halfHeight = container.size[ 1 ] / 2;
+
+			this.moveState.yawLeft   = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth  ) / halfWidth;
+			this.moveState.pitchDown =   ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight;
+
+			this.updateRotationVector();
+
+		}
+
+	};
+
+	this.mouseup = function( event ) {
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( this.dragToLook ) {
+
+			this.mouseStatus --;
+
+			this.moveState.yawLeft = this.moveState.pitchDown = 0;
+
+		} else {
+
+			switch ( event.button ) {
+
+				case 0: this.moveState.forward = 0; break;
+				case 2: this.moveState.back = 0; break;
+
+			}
+
+			this.updateMovementVector();
+
+		}
+
+		this.updateRotationVector();
+
+	};
+
+	this.update = function( delta ) {
+
+		var moveMult = delta * this.movementSpeed;
+		var rotMult = delta * this.rollSpeed;
+
+		this.object.translateX( this.moveVector.x * moveMult );
+		this.object.translateY( this.moveVector.y * moveMult );
+		this.object.translateZ( this.moveVector.z * moveMult );
+
+		this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();
+		this.object.quaternion.multiply( this.tmpQuaternion );
+
+		// expose the rotation vector for convenience
+		this.object.rotation.setFromQuaternion( this.object.quaternion, this.object.rotation.order );
+
+
+	};
+
+	this.updateMovementVector = function() {
+
+		var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0;
+
+		this.moveVector.x = ( - this.moveState.left    + this.moveState.right );
+		this.moveVector.y = ( - this.moveState.down    + this.moveState.up );
+		this.moveVector.z = ( - forward + this.moveState.back );
+
+		//console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
+
+	};
+
+	this.updateRotationVector = function() {
+
+		this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp );
+		this.rotationVector.y = ( - this.moveState.yawRight  + this.moveState.yawLeft );
+		this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft );
+
+		//console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
+
+	};
+
+	this.getContainerDimensions = function() {
+
+		if ( this.domElement != document ) {
+
+			return {
+				size	: [ this.domElement.offsetWidth, this.domElement.offsetHeight ],
+				offset	: [ this.domElement.offsetLeft,  this.domElement.offsetTop ]
+			};
+
+		} else {
+
+			return {
+				size	: [ window.innerWidth, window.innerHeight ],
+				offset	: [ 0, 0 ]
+			};
+
+		}
+
+	};
+
+	function bind( scope, fn ) {
+
+		return function () {
+
+			fn.apply( scope, arguments );
+
+		};
+
+	}
+
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _mousedown, false );
+		this.domElement.removeEventListener( 'mousemove', _mousemove, false );
+		this.domElement.removeEventListener( 'mouseup', _mouseup, false );
+
+		window.removeEventListener( 'keydown', _keydown, false );
+		window.removeEventListener( 'keyup', _keyup, false );
+
+	};
+
+	var _mousemove = bind( this, this.mousemove );
+	var _mousedown = bind( this, this.mousedown );
+	var _mouseup = bind( this, this.mouseup );
+	var _keydown = bind( this, this.keydown );
+	var _keyup = bind( this, this.keyup );
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+
+	this.domElement.addEventListener( 'mousemove', _mousemove, false );
+	this.domElement.addEventListener( 'mousedown', _mousedown, false );
+	this.domElement.addEventListener( 'mouseup',   _mouseup, false );
+
+	window.addEventListener( 'keydown', _keydown, false );
+	window.addEventListener( 'keyup',   _keyup, false );
+
+	this.updateMovementVector();
+	this.updateRotationVector();
+
+};

+ 1016 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/OrbitControls.js

@@ -0,0 +1,1016 @@
+/**
+ * @author qiao / https://github.com/qiao
+ * @author mrdoob / http://mrdoob.com
+ * @author alteredq / http://alteredqualia.com/
+ * @author WestLangley / http://github.com/WestLangley
+ * @author erich666 / http://erichaines.com
+ */
+
+// This set of controls performs orbiting, dollying (zooming), and panning.
+// Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
+//
+//    Orbit - left mouse / touch: one finger move
+//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+//    Pan - right mouse, or arrow keys / touch: three finger swipe
+
+THREE.OrbitControls = function ( object, domElement ) {
+
+	this.object = object;
+
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// Set to false to disable this control
+	this.enabled = true;
+
+	// "target" sets the location of focus, where the object orbits around
+	this.target = new THREE.Vector3();
+
+	// How far you can dolly in and out ( PerspectiveCamera only )
+	this.minDistance = 0;
+	this.maxDistance = Infinity;
+
+	// How far you can zoom in and out ( OrthographicCamera only )
+	this.minZoom = 0;
+	this.maxZoom = Infinity;
+
+	// How far you can orbit vertically, upper and lower limits.
+	// Range is 0 to Math.PI radians.
+	this.minPolarAngle = 0; // radians
+	this.maxPolarAngle = Math.PI; // radians
+
+	// How far you can orbit horizontally, upper and lower limits.
+	// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+	this.minAzimuthAngle = - Infinity; // radians
+	this.maxAzimuthAngle = Infinity; // radians
+
+	// Set to true to enable damping (inertia)
+	// If damping is enabled, you must call controls.update() in your animation loop
+	this.enableDamping = false;
+	this.dampingFactor = 0.25;
+
+	// This option actually enables dollying in and out; left as "zoom" for backwards compatibility.
+	// Set to false to disable zooming
+	this.enableZoom = true;
+	this.zoomSpeed = 1.0;
+
+	// Set to false to disable rotating
+	this.enableRotate = true;
+	this.rotateSpeed = 1.0;
+
+	// Set to false to disable panning
+	this.enablePan = true;
+	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
+
+	// Set to true to automatically rotate around the target
+	// If auto-rotate is enabled, you must call controls.update() in your animation loop
+	this.autoRotate = false;
+	this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+
+	// Set to false to disable use of the keys
+	this.enableKeys = true;
+
+	// The four arrow keys
+	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+
+	// Mouse buttons
+	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+
+	// for reset
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.zoom0 = this.object.zoom;
+
+	//
+	// public methods
+	//
+
+	this.getPolarAngle = function () {
+
+		return spherical.phi;
+
+	};
+
+	this.getAzimuthalAngle = function () {
+
+		return spherical.theta;
+
+	};
+
+	this.reset = function () {
+
+		scope.target.copy( scope.target0 );
+		scope.object.position.copy( scope.position0 );
+		scope.object.zoom = scope.zoom0;
+
+		scope.object.updateProjectionMatrix();
+		scope.dispatchEvent( changeEvent );
+
+		scope.update();
+
+		state = STATE.NONE;
+
+	};
+
+	// this method is exposed, but perhaps it would be better if we can make it private...
+	this.update = function () {
+
+		var offset = new THREE.Vector3();
+
+		// so camera.up is the orbit axis
+		var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
+		var quatInverse = quat.clone().inverse();
+
+		var lastPosition = new THREE.Vector3();
+		var lastQuaternion = new THREE.Quaternion();
+
+		return function update() {
+
+			var position = scope.object.position;
+
+			offset.copy( position ).sub( scope.target );
+
+			// rotate offset to "y-axis-is-up" space
+			offset.applyQuaternion( quat );
+
+			// angle from z-axis around y-axis
+			spherical.setFromVector3( offset );
+
+			if ( scope.autoRotate && state === STATE.NONE ) {
+
+				rotateLeft( getAutoRotationAngle() );
+
+			}
+
+			spherical.theta += sphericalDelta.theta;
+			spherical.phi += sphericalDelta.phi;
+
+			// restrict theta to be between desired limits
+			spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );
+
+			// restrict phi to be between desired limits
+			spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );
+
+			spherical.makeSafe();
+
+
+			spherical.radius *= scale;
+
+			// restrict radius to be between desired limits
+			spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );
+
+			// move target to panned location
+			scope.target.add( panOffset );
+
+			offset.setFromSpherical( spherical );
+
+			// rotate offset back to "camera-up-vector-is-up" space
+			offset.applyQuaternion( quatInverse );
+
+			position.copy( scope.target ).add( offset );
+
+			scope.object.lookAt( scope.target );
+
+			if ( scope.enableDamping === true ) {
+
+				sphericalDelta.theta *= ( 1 - scope.dampingFactor );
+				sphericalDelta.phi *= ( 1 - scope.dampingFactor );
+
+			} else {
+
+				sphericalDelta.set( 0, 0, 0 );
+
+			}
+
+			scale = 1;
+			panOffset.set( 0, 0, 0 );
+
+			// update condition is:
+			// min(camera displacement, camera rotation in radians)^2 > EPS
+			// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+			if ( zoomChanged ||
+				lastPosition.distanceToSquared( scope.object.position ) > EPS ||
+				8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {
+
+				scope.dispatchEvent( changeEvent );
+
+				lastPosition.copy( scope.object.position );
+				lastQuaternion.copy( scope.object.quaternion );
+				zoomChanged = false;
+
+				return true;
+
+			}
+
+			return false;
+
+		};
+
+	}();
+
+	this.dispose = function () {
+
+		scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );
+		scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );
+		scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );
+
+		scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );
+		scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );
+		scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+		document.removeEventListener( 'mouseup', onMouseUp, false );
+
+		window.removeEventListener( 'keydown', onKeyDown, false );
+
+		//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
+
+	};
+
+	//
+	// internals
+	//
+
+	var scope = this;
+
+	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start' };
+	var endEvent = { type: 'end' };
+
+	var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };
+
+	var state = STATE.NONE;
+
+	var EPS = 0.000001;
+
+	// current position in spherical coordinates
+	var spherical = new THREE.Spherical();
+	var sphericalDelta = new THREE.Spherical();
+
+	var scale = 1;
+	var panOffset = new THREE.Vector3();
+	var zoomChanged = false;
+
+	var rotateStart = new THREE.Vector2();
+	var rotateEnd = new THREE.Vector2();
+	var rotateDelta = new THREE.Vector2();
+
+	var panStart = new THREE.Vector2();
+	var panEnd = new THREE.Vector2();
+	var panDelta = new THREE.Vector2();
+
+	var dollyStart = new THREE.Vector2();
+	var dollyEnd = new THREE.Vector2();
+	var dollyDelta = new THREE.Vector2();
+
+	function getAutoRotationAngle() {
+
+		return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+	}
+
+	function getZoomScale() {
+
+		return Math.pow( 0.95, scope.zoomSpeed );
+
+	}
+
+	function rotateLeft( angle ) {
+
+		sphericalDelta.theta -= angle;
+
+	}
+
+	function rotateUp( angle ) {
+
+		sphericalDelta.phi -= angle;
+
+	}
+
+	var panLeft = function () {
+
+		var v = new THREE.Vector3();
+
+		return function panLeft( distance, objectMatrix ) {
+
+			v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
+			v.multiplyScalar( - distance );
+
+			panOffset.add( v );
+
+		};
+
+	}();
+
+	var panUp = function () {
+
+		var v = new THREE.Vector3();
+
+		return function panUp( distance, objectMatrix ) {
+
+			v.setFromMatrixColumn( objectMatrix, 1 ); // get Y column of objectMatrix
+			v.multiplyScalar( distance );
+
+			panOffset.add( v );
+
+		};
+
+	}();
+
+	// deltaX and deltaY are in pixels; right and down are positive
+	var pan = function () {
+
+		var offset = new THREE.Vector3();
+
+		return function pan( deltaX, deltaY ) {
+
+			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+			if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+				// perspective
+				var position = scope.object.position;
+				offset.copy( position ).sub( scope.target );
+				var targetDistance = offset.length();
+
+				// half of the fov is center to top of screen
+				targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
+
+				// we actually don't use screenWidth, since perspective camera is fixed to screen height
+				panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );
+				panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );
+
+			} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+				// orthographic
+				panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
+				panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
+
+			} else {
+
+				// camera neither orthographic nor perspective
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+				scope.enablePan = false;
+
+			}
+
+		};
+
+	}();
+
+	function dollyIn( dollyScale ) {
+
+		if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+			scale /= dollyScale;
+
+		} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+			scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );
+			scope.object.updateProjectionMatrix();
+			zoomChanged = true;
+
+		} else {
+
+			console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+			scope.enableZoom = false;
+
+		}
+
+	}
+
+	function dollyOut( dollyScale ) {
+
+		if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+			scale *= dollyScale;
+
+		} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+			scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );
+			scope.object.updateProjectionMatrix();
+			zoomChanged = true;
+
+		} else {
+
+			console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+			scope.enableZoom = false;
+
+		}
+
+	}
+
+	//
+	// event callbacks - update the object state
+	//
+
+	function handleMouseDownRotate( event ) {
+
+		//console.log( 'handleMouseDownRotate' );
+
+		rotateStart.set( event.clientX, event.clientY );
+
+	}
+
+	function handleMouseDownDolly( event ) {
+
+		//console.log( 'handleMouseDownDolly' );
+
+		dollyStart.set( event.clientX, event.clientY );
+
+	}
+
+	function handleMouseDownPan( event ) {
+
+		//console.log( 'handleMouseDownPan' );
+
+		panStart.set( event.clientX, event.clientY );
+
+	}
+
+	function handleMouseMoveRotate( event ) {
+
+		//console.log( 'handleMouseMoveRotate' );
+
+		rotateEnd.set( event.clientX, event.clientY );
+		rotateDelta.subVectors( rotateEnd, rotateStart );
+
+		var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+		// rotating across whole screen goes 360 degrees around
+		rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+
+		// rotating up and down along whole screen attempts to go 360, but limited to 180
+		rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+
+		rotateStart.copy( rotateEnd );
+
+		scope.update();
+
+	}
+
+	function handleMouseMoveDolly( event ) {
+
+		//console.log( 'handleMouseMoveDolly' );
+
+		dollyEnd.set( event.clientX, event.clientY );
+
+		dollyDelta.subVectors( dollyEnd, dollyStart );
+
+		if ( dollyDelta.y > 0 ) {
+
+			dollyIn( getZoomScale() );
+
+		} else if ( dollyDelta.y < 0 ) {
+
+			dollyOut( getZoomScale() );
+
+		}
+
+		dollyStart.copy( dollyEnd );
+
+		scope.update();
+
+	}
+
+	function handleMouseMovePan( event ) {
+
+		//console.log( 'handleMouseMovePan' );
+
+		panEnd.set( event.clientX, event.clientY );
+
+		panDelta.subVectors( panEnd, panStart );
+
+		pan( panDelta.x, panDelta.y );
+
+		panStart.copy( panEnd );
+
+		scope.update();
+
+	}
+
+	function handleMouseUp( event ) {
+
+		// console.log( 'handleMouseUp' );
+
+	}
+
+	function handleMouseWheel( event ) {
+
+		// console.log( 'handleMouseWheel' );
+
+		if ( event.deltaY < 0 ) {
+
+			dollyOut( getZoomScale() );
+
+		} else if ( event.deltaY > 0 ) {
+
+			dollyIn( getZoomScale() );
+
+		}
+
+		scope.update();
+
+	}
+
+	function handleKeyDown( event ) {
+
+		//console.log( 'handleKeyDown' );
+
+		switch ( event.keyCode ) {
+
+			case scope.keys.UP:
+				pan( 0, scope.keyPanSpeed );
+				scope.update();
+				break;
+
+			case scope.keys.BOTTOM:
+				pan( 0, - scope.keyPanSpeed );
+				scope.update();
+				break;
+
+			case scope.keys.LEFT:
+				pan( scope.keyPanSpeed, 0 );
+				scope.update();
+				break;
+
+			case scope.keys.RIGHT:
+				pan( - scope.keyPanSpeed, 0 );
+				scope.update();
+				break;
+
+		}
+
+	}
+
+	function handleTouchStartRotate( event ) {
+
+		//console.log( 'handleTouchStartRotate' );
+
+		rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+	}
+
+	function handleTouchStartDolly( event ) {
+
+		//console.log( 'handleTouchStartDolly' );
+
+		var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+		var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+
+		var distance = Math.sqrt( dx * dx + dy * dy );
+
+		dollyStart.set( 0, distance );
+
+	}
+
+	function handleTouchStartPan( event ) {
+
+		//console.log( 'handleTouchStartPan' );
+
+		panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+	}
+
+	function handleTouchMoveRotate( event ) {
+
+		//console.log( 'handleTouchMoveRotate' );
+
+		rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+		rotateDelta.subVectors( rotateEnd, rotateStart );
+
+		var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+		// rotating across whole screen goes 360 degrees around
+		rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+
+		// rotating up and down along whole screen attempts to go 360, but limited to 180
+		rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+
+		rotateStart.copy( rotateEnd );
+
+		scope.update();
+
+	}
+
+	function handleTouchMoveDolly( event ) {
+
+		//console.log( 'handleTouchMoveDolly' );
+
+		var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+		var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+
+		var distance = Math.sqrt( dx * dx + dy * dy );
+
+		dollyEnd.set( 0, distance );
+
+		dollyDelta.subVectors( dollyEnd, dollyStart );
+
+		if ( dollyDelta.y > 0 ) {
+
+			dollyOut( getZoomScale() );
+
+		} else if ( dollyDelta.y < 0 ) {
+
+			dollyIn( getZoomScale() );
+
+		}
+
+		dollyStart.copy( dollyEnd );
+
+		scope.update();
+
+	}
+
+	function handleTouchMovePan( event ) {
+
+		//console.log( 'handleTouchMovePan' );
+
+		panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+
+		panDelta.subVectors( panEnd, panStart );
+
+		pan( panDelta.x, panDelta.y );
+
+		panStart.copy( panEnd );
+
+		scope.update();
+
+	}
+
+	function handleTouchEnd( event ) {
+
+		//console.log( 'handleTouchEnd' );
+
+	}
+
+	//
+	// event handlers - FSM: listen for events and reset state
+	//
+
+	function onMouseDown( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		event.preventDefault();
+
+		if ( event.button === scope.mouseButtons.ORBIT ) {
+
+			if ( scope.enableRotate === false ) return;
+
+			handleMouseDownRotate( event );
+
+			state = STATE.ROTATE;
+
+		} else if ( event.button === scope.mouseButtons.ZOOM ) {
+
+			if ( scope.enableZoom === false ) return;
+
+			handleMouseDownDolly( event );
+
+			state = STATE.DOLLY;
+
+		} else if ( event.button === scope.mouseButtons.PAN ) {
+
+			if ( scope.enablePan === false ) return;
+
+			handleMouseDownPan( event );
+
+			state = STATE.PAN;
+
+		}
+
+		if ( state !== STATE.NONE ) {
+
+			document.addEventListener( 'mousemove', onMouseMove, false );
+			document.addEventListener( 'mouseup', onMouseUp, false );
+
+			scope.dispatchEvent( startEvent );
+
+		}
+
+	}
+
+	function onMouseMove( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		event.preventDefault();
+
+		if ( state === STATE.ROTATE ) {
+
+			if ( scope.enableRotate === false ) return;
+
+			handleMouseMoveRotate( event );
+
+		} else if ( state === STATE.DOLLY ) {
+
+			if ( scope.enableZoom === false ) return;
+
+			handleMouseMoveDolly( event );
+
+		} else if ( state === STATE.PAN ) {
+
+			if ( scope.enablePan === false ) return;
+
+			handleMouseMovePan( event );
+
+		}
+
+	}
+
+	function onMouseUp( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		handleMouseUp( event );
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+		document.removeEventListener( 'mouseup', onMouseUp, false );
+
+		scope.dispatchEvent( endEvent );
+
+		state = STATE.NONE;
+
+	}
+
+	function onMouseWheel( event ) {
+
+		if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		handleMouseWheel( event );
+
+		scope.dispatchEvent( startEvent ); // not sure why these are here...
+		scope.dispatchEvent( endEvent );
+
+	}
+
+	function onKeyDown( event ) {
+
+		if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;
+
+		handleKeyDown( event );
+
+	}
+
+	function onTouchStart( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:	// one-fingered touch: rotate
+
+				if ( scope.enableRotate === false ) return;
+
+				handleTouchStartRotate( event );
+
+				state = STATE.TOUCH_ROTATE;
+
+				break;
+
+			case 2:	// two-fingered touch: dolly
+
+				if ( scope.enableZoom === false ) return;
+
+				handleTouchStartDolly( event );
+
+				state = STATE.TOUCH_DOLLY;
+
+				break;
+
+			case 3: // three-fingered touch: pan
+
+				if ( scope.enablePan === false ) return;
+
+				handleTouchStartPan( event );
+
+				state = STATE.TOUCH_PAN;
+
+				break;
+
+			default:
+
+				state = STATE.NONE;
+
+		}
+
+		if ( state !== STATE.NONE ) {
+
+			scope.dispatchEvent( startEvent );
+
+		}
+
+	}
+
+	function onTouchMove( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.touches.length ) {
+
+			case 1: // one-fingered touch: rotate
+
+				if ( scope.enableRotate === false ) return;
+				if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?...
+
+				handleTouchMoveRotate( event );
+
+				break;
+
+			case 2: // two-fingered touch: dolly
+
+				if ( scope.enableZoom === false ) return;
+				if ( state !== STATE.TOUCH_DOLLY ) return; // is this needed?...
+
+				handleTouchMoveDolly( event );
+
+				break;
+
+			case 3: // three-fingered touch: pan
+
+				if ( scope.enablePan === false ) return;
+				if ( state !== STATE.TOUCH_PAN ) return; // is this needed?...
+
+				handleTouchMovePan( event );
+
+				break;
+
+			default:
+
+				state = STATE.NONE;
+
+		}
+
+	}
+
+	function onTouchEnd( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		handleTouchEnd( event );
+
+		scope.dispatchEvent( endEvent );
+
+		state = STATE.NONE;
+
+	}
+
+	function onContextMenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	//
+
+	scope.domElement.addEventListener( 'contextmenu', onContextMenu, false );
+
+	scope.domElement.addEventListener( 'mousedown', onMouseDown, false );
+	scope.domElement.addEventListener( 'wheel', onMouseWheel, false );
+
+	scope.domElement.addEventListener( 'touchstart', onTouchStart, false );
+	scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
+	scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
+
+	window.addEventListener( 'keydown', onKeyDown, false );
+
+	// force an update at start
+
+	this.update();
+
+};
+
+THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
+
+Object.defineProperties( THREE.OrbitControls.prototype, {
+
+	center: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .center has been renamed to .target' );
+			return this.target;
+
+		}
+
+	},
+
+	// backward compatibility
+
+	noZoom: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
+			return ! this.enableZoom;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
+			this.enableZoom = ! value;
+
+		}
+
+	},
+
+	noRotate: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
+			return ! this.enableRotate;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
+			this.enableRotate = ! value;
+
+		}
+
+	},
+
+	noPan: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
+			return ! this.enablePan;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
+			this.enablePan = ! value;
+
+		}
+
+	},
+
+	noKeys: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
+			return ! this.enableKeys;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
+			this.enableKeys = ! value;
+
+		}
+
+	},
+
+	staticMoving: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
+			return ! this.enableDamping;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
+			this.enableDamping = ! value;
+
+		}
+
+	},
+
+	dynamicDampingFactor: {
+
+		get: function () {
+
+			console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
+			return this.dampingFactor;
+
+		},
+
+		set: function ( value ) {
+
+			console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
+			this.dampingFactor = value;
+
+		}
+
+	}
+
+} );

+ 636 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/OrthographicTrackballControls.js

@@ -0,0 +1,636 @@
+/**
+ * @author Eberhard Graether / http://egraether.com/
+ * @author Mark Lundin 	/ http://mark-lundin.com
+ * @author Patrick Fuller / http://patrick-fuller.com
+ * @author Max Smolens / https://github.com/msmolens
+ */
+
+THREE.OrthographicTrackballControls = function ( object, domElement ) {
+
+	var _this = this;
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
+
+	this.object = object;
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// API
+
+	this.enabled = true;
+
+	this.screen = { left: 0, top: 0, width: 0, height: 0 };
+
+	this.radius = 0;
+
+	this.rotateSpeed = 1.0;
+	this.zoomSpeed = 1.2;
+
+	this.noRotate = false;
+	this.noZoom = false;
+	this.noPan = false;
+	this.noRoll = false;
+
+	this.staticMoving = false;
+	this.dynamicDampingFactor = 0.2;
+
+	this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
+
+	// internals
+
+	this.target = new THREE.Vector3();
+
+	var EPS = 0.000001;
+
+	var _changed = true;
+
+	var _state = STATE.NONE,
+	_prevState = STATE.NONE,
+
+	_eye = new THREE.Vector3(),
+
+	_rotateStart = new THREE.Vector3(),
+	_rotateEnd = new THREE.Vector3(),
+
+	_zoomStart = new THREE.Vector2(),
+	_zoomEnd = new THREE.Vector2(),
+
+	_touchZoomDistanceStart = 0,
+	_touchZoomDistanceEnd = 0,
+
+	_panStart = new THREE.Vector2(),
+	_panEnd = new THREE.Vector2();
+
+	// for reset
+
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.up0 = this.object.up.clone();
+
+	this.left0 = this.object.left;
+	this.right0 = this.object.right;
+	this.top0 = this.object.top;
+	this.bottom0 = this.object.bottom;
+
+	// events
+
+	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start' };
+	var endEvent = { type: 'end' };
+
+
+	// methods
+
+	this.handleResize = function () {
+
+		if ( this.domElement === document ) {
+
+			this.screen.left = 0;
+			this.screen.top = 0;
+			this.screen.width = window.innerWidth;
+			this.screen.height = window.innerHeight;
+
+		} else {
+
+			var box = this.domElement.getBoundingClientRect();
+			// adjustments come from similar code in the jquery offset() function
+			var d = this.domElement.ownerDocument.documentElement;
+			this.screen.left = box.left + window.pageXOffset - d.clientLeft;
+			this.screen.top = box.top + window.pageYOffset - d.clientTop;
+			this.screen.width = box.width;
+			this.screen.height = box.height;
+
+		}
+
+		this.radius = 0.5 * Math.min( this.screen.width, this.screen.height );
+
+		this.left0 = this.object.left;
+		this.right0 = this.object.right;
+		this.top0 = this.object.top;
+		this.bottom0 = this.object.bottom;
+
+	};
+
+	this.handleEvent = function ( event ) {
+
+		if ( typeof this[ event.type ] == 'function' ) {
+
+			this[ event.type ]( event );
+
+		}
+
+	};
+
+	var getMouseOnScreen = ( function () {
+
+		var vector = new THREE.Vector2();
+
+		return function getMouseOnScreen( pageX, pageY ) {
+
+			vector.set(
+				( pageX - _this.screen.left ) / _this.screen.width,
+				( pageY - _this.screen.top ) / _this.screen.height
+			);
+
+			return vector;
+
+		};
+
+	}() );
+
+	var getMouseProjectionOnBall = ( function () {
+
+		var vector = new THREE.Vector3();
+		var objectUp = new THREE.Vector3();
+		var mouseOnBall = new THREE.Vector3();
+
+		return function getMouseProjectionOnBall( pageX, pageY ) {
+
+			mouseOnBall.set(
+				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / _this.radius,
+				( _this.screen.height * 0.5 + _this.screen.top - pageY ) / _this.radius,
+				0.0
+			);
+
+			var length = mouseOnBall.length();
+
+			if ( _this.noRoll ) {
+
+				if ( length < Math.SQRT1_2 ) {
+
+					mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+
+				} else {
+
+					mouseOnBall.z = .5 / length;
+
+				}
+
+			} else if ( length > 1.0 ) {
+
+				mouseOnBall.normalize();
+
+			} else {
+
+				mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+
+			}
+
+			_eye.copy( _this.object.position ).sub( _this.target );
+
+			vector.copy( _this.object.up ).setLength( mouseOnBall.y );
+			vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
+			vector.add( _eye.setLength( mouseOnBall.z ) );
+
+			return vector;
+
+		};
+
+	}() );
+
+	this.rotateCamera = ( function() {
+
+		var axis = new THREE.Vector3(),
+			quaternion = new THREE.Quaternion();
+
+
+		return function rotateCamera() {
+
+			var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+
+			if ( angle ) {
+
+				axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
+
+				angle *= _this.rotateSpeed;
+
+				quaternion.setFromAxisAngle( axis, - angle );
+
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
+
+				_rotateEnd.applyQuaternion( quaternion );
+
+				if ( _this.staticMoving ) {
+
+					_rotateStart.copy( _rotateEnd );
+
+				} else {
+
+					quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
+					_rotateStart.applyQuaternion( quaternion );
+
+				}
+
+				_changed = true;
+
+			}
+
+		}
+
+	}() );
+
+	this.zoomCamera = function () {
+
+		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
+
+			var factor = _touchZoomDistanceEnd / _touchZoomDistanceStart;
+			_touchZoomDistanceStart = _touchZoomDistanceEnd;
+
+			_this.object.zoom *= factor;
+
+			_changed = true;
+
+		} else {
+
+			var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
+
+			if ( Math.abs( factor - 1.0 ) > EPS && factor > 0.0 ) {
+
+				_this.object.zoom /= factor;
+
+				if ( _this.staticMoving ) {
+
+					_zoomStart.copy( _zoomEnd );
+
+				} else {
+
+					_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
+
+				}
+
+				_changed = true;
+
+			}
+
+		}
+
+	};
+
+	this.panCamera = ( function() {
+
+		var mouseChange = new THREE.Vector2(),
+			objectUp = new THREE.Vector3(),
+			pan = new THREE.Vector3();
+
+		return function panCamera() {
+
+			mouseChange.copy( _panEnd ).sub( _panStart );
+
+			if ( mouseChange.lengthSq() ) {
+
+				// Scale movement to keep clicked/dragged position under cursor
+				var scale_x = ( _this.object.right - _this.object.left ) / _this.object.zoom;
+				var scale_y = ( _this.object.top - _this.object.bottom ) / _this.object.zoom;
+				mouseChange.x *= scale_x;
+				mouseChange.y *= scale_y;
+
+				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
+				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
+
+				_this.object.position.add( pan );
+				_this.target.add( pan );
+
+				if ( _this.staticMoving ) {
+
+					_panStart.copy( _panEnd );
+
+				} else {
+
+					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+
+				}
+
+				_changed = true;
+
+			}
+
+		}
+
+	}() );
+
+	this.update = function () {
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		if ( ! _this.noRotate ) {
+
+			_this.rotateCamera();
+
+		}
+
+		if ( ! _this.noZoom ) {
+
+			_this.zoomCamera();
+
+			if ( _changed ) {
+
+				_this.object.updateProjectionMatrix();
+
+			}
+
+		}
+
+		if ( ! _this.noPan ) {
+
+			_this.panCamera();
+
+		}
+
+		_this.object.position.addVectors( _this.target, _eye );
+
+		_this.object.lookAt( _this.target );
+
+		if ( _changed ) {
+
+			_this.dispatchEvent( changeEvent );
+
+			_changed = false;
+
+		}
+
+	};
+
+	this.reset = function () {
+
+		_state = STATE.NONE;
+		_prevState = STATE.NONE;
+
+		_this.target.copy( _this.target0 );
+		_this.object.position.copy( _this.position0 );
+		_this.object.up.copy( _this.up0 );
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		_this.object.left = _this.left0;
+		_this.object.right = _this.right0;
+		_this.object.top = _this.top0;
+		_this.object.bottom = _this.bottom0;
+
+		_this.object.lookAt( _this.target );
+
+		_this.dispatchEvent( changeEvent );
+
+		_changed = false;
+
+	};
+
+	// listeners
+
+	function keydown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		window.removeEventListener( 'keydown', keydown );
+
+		_prevState = _state;
+
+		if ( _state !== STATE.NONE ) {
+
+			return;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
+
+			_state = STATE.ROTATE;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
+
+			_state = STATE.ZOOM;
+
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
+
+			_state = STATE.PAN;
+
+		}
+
+	}
+
+	function keyup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		_state = _prevState;
+
+		window.addEventListener( 'keydown', keydown, false );
+
+	}
+
+	function mousedown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.NONE ) {
+
+			_state = event.button;
+
+		}
+
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
+
+			_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+			_rotateEnd.copy( _rotateStart );
+
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
+
+			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_zoomEnd.copy( _zoomStart );
+
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
+
+			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_panEnd.copy( _panStart )
+
+		}
+
+		document.addEventListener( 'mousemove', mousemove, false );
+		document.addEventListener( 'mouseup', mouseup, false );
+
+		_this.dispatchEvent( startEvent );
+
+	}
+
+	function mousemove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
+
+			_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
+
+			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
+
+			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		}
+
+	}
+
+	function mouseup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		_state = STATE.NONE;
+
+		document.removeEventListener( 'mousemove', mousemove );
+		document.removeEventListener( 'mouseup', mouseup );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function mousewheel( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		_zoomStart.y += event.deltaY * 0.01;
+		_this.dispatchEvent( startEvent );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function touchstart( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_state = STATE.TOUCH_ROTATE;
+				_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateEnd.copy( _rotateStart );
+				break;
+
+			case 2:
+				_state = STATE.TOUCH_ZOOM_PAN;
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panStart.copy( getMouseOnScreen( x, y ) );
+				_panEnd.copy( _panStart );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+		_this.dispatchEvent( startEvent );
+
+	}
+
+	function touchmove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				break;
+
+			case 2:
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+
+	}
+
+	function touchend( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateStart.copy( _rotateEnd );
+				break;
+
+			case 2:
+				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				_panStart.copy( _panEnd );
+				break;
+
+		}
+
+		_state = STATE.NONE;
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'wheel', mousewheel, false );
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
+
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	};
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
+	this.domElement.addEventListener( 'wheel', mousewheel, false );
+
+	this.domElement.addEventListener( 'touchstart', touchstart, false );
+	this.domElement.addEventListener( 'touchend', touchend, false );
+	this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+	window.addEventListener( 'keydown', keydown, false );
+	window.addEventListener( 'keyup', keyup, false );
+
+	this.handleResize();
+
+	// force an update at start
+	this.update();
+
+};
+
+THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.OrthographicTrackballControls.prototype.constructor = THREE.OrthographicTrackballControls;

+ 69 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/PointerLockControls.js

@@ -0,0 +1,69 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.PointerLockControls = function ( camera ) {
+
+	var scope = this;
+
+	camera.rotation.set( 0, 0, 0 );
+
+	var pitchObject = new THREE.Object3D();
+	pitchObject.add( camera );
+
+	var yawObject = new THREE.Object3D();
+	yawObject.position.y = 10;
+	yawObject.add( pitchObject );
+
+	var PI_2 = Math.PI / 2;
+
+	var onMouseMove = function ( event ) {
+
+		if ( scope.enabled === false ) return;
+
+		var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0;
+		var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0;
+
+		yawObject.rotation.y -= movementX * 0.002;
+		pitchObject.rotation.x -= movementY * 0.002;
+
+		pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) );
+
+	};
+
+	this.dispose = function() {
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+
+	};
+
+	document.addEventListener( 'mousemove', onMouseMove, false );
+
+	this.enabled = false;
+
+	this.getObject = function () {
+
+		return yawObject;
+
+	};
+
+	this.getDirection = function() {
+
+		// assumes the camera itself is not rotated
+
+		var direction = new THREE.Vector3( 0, 0, - 1 );
+		var rotation = new THREE.Euler( 0, 0, 0, "YXZ" );
+
+		return function( v ) {
+
+			rotation.set( pitchObject.rotation.x, yawObject.rotation.y, 0 );
+
+			v.copy( direction ).applyEuler( rotation );
+
+			return v;
+
+		};
+
+	}();
+
+};

+ 623 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/TrackballControls.js

@@ -0,0 +1,623 @@
+/**
+ * @author Eberhard Graether / http://egraether.com/
+ * @author Mark Lundin 	/ http://mark-lundin.com
+ * @author Simone Manini / http://daron1337.github.io
+ * @author Luca Antiga 	/ http://lantiga.github.io
+ */
+
+THREE.TrackballControls = function ( object, domElement ) {
+
+	var _this = this;
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
+
+	this.object = object;
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// API
+
+	this.enabled = true;
+
+	this.screen = { left: 0, top: 0, width: 0, height: 0 };
+
+	this.rotateSpeed = 1.0;
+	this.zoomSpeed = 1.2;
+	this.panSpeed = 0.3;
+
+	this.noRotate = false;
+	this.noZoom = false;
+	this.noPan = false;
+
+	this.staticMoving = false;
+	this.dynamicDampingFactor = 0.2;
+
+	this.minDistance = 0;
+	this.maxDistance = Infinity;
+
+	this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
+
+	// internals
+
+	this.target = new THREE.Vector3();
+
+	var EPS = 0.000001;
+
+	var lastPosition = new THREE.Vector3();
+
+	var _state = STATE.NONE,
+	_prevState = STATE.NONE,
+
+	_eye = new THREE.Vector3(),
+
+	_movePrev = new THREE.Vector2(),
+	_moveCurr = new THREE.Vector2(),
+
+	_lastAxis = new THREE.Vector3(),
+	_lastAngle = 0,
+
+	_zoomStart = new THREE.Vector2(),
+	_zoomEnd = new THREE.Vector2(),
+
+	_touchZoomDistanceStart = 0,
+	_touchZoomDistanceEnd = 0,
+
+	_panStart = new THREE.Vector2(),
+	_panEnd = new THREE.Vector2();
+
+	// for reset
+
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.up0 = this.object.up.clone();
+
+	// events
+
+	var changeEvent = { type: 'change' };
+	var startEvent = { type: 'start' };
+	var endEvent = { type: 'end' };
+
+
+	// methods
+
+	this.handleResize = function () {
+
+		if ( this.domElement === document ) {
+
+			this.screen.left = 0;
+			this.screen.top = 0;
+			this.screen.width = window.innerWidth;
+			this.screen.height = window.innerHeight;
+
+		} else {
+
+			var box = this.domElement.getBoundingClientRect();
+			// adjustments come from similar code in the jquery offset() function
+			var d = this.domElement.ownerDocument.documentElement;
+			this.screen.left = box.left + window.pageXOffset - d.clientLeft;
+			this.screen.top = box.top + window.pageYOffset - d.clientTop;
+			this.screen.width = box.width;
+			this.screen.height = box.height;
+
+		}
+
+	};
+
+	this.handleEvent = function ( event ) {
+
+		if ( typeof this[ event.type ] == 'function' ) {
+
+			this[ event.type ]( event );
+
+		}
+
+	};
+
+	var getMouseOnScreen = ( function () {
+
+		var vector = new THREE.Vector2();
+
+		return function getMouseOnScreen( pageX, pageY ) {
+
+			vector.set(
+				( pageX - _this.screen.left ) / _this.screen.width,
+				( pageY - _this.screen.top ) / _this.screen.height
+			);
+
+			return vector;
+
+		};
+
+	}() );
+
+	var getMouseOnCircle = ( function () {
+
+		var vector = new THREE.Vector2();
+
+		return function getMouseOnCircle( pageX, pageY ) {
+
+			vector.set(
+				( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
+				( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional
+			);
+
+			return vector;
+
+		};
+
+	}() );
+
+	this.rotateCamera = ( function() {
+
+		var axis = new THREE.Vector3(),
+			quaternion = new THREE.Quaternion(),
+			eyeDirection = new THREE.Vector3(),
+			objectUpDirection = new THREE.Vector3(),
+			objectSidewaysDirection = new THREE.Vector3(),
+			moveDirection = new THREE.Vector3(),
+			angle;
+
+		return function rotateCamera() {
+
+			moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
+			angle = moveDirection.length();
+
+			if ( angle ) {
+
+				_eye.copy( _this.object.position ).sub( _this.target );
+
+				eyeDirection.copy( _eye ).normalize();
+				objectUpDirection.copy( _this.object.up ).normalize();
+				objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize();
+
+				objectUpDirection.setLength( _moveCurr.y - _movePrev.y );
+				objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x );
+
+				moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) );
+
+				axis.crossVectors( moveDirection, _eye ).normalize();
+
+				angle *= _this.rotateSpeed;
+				quaternion.setFromAxisAngle( axis, angle );
+
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
+
+				_lastAxis.copy( axis );
+				_lastAngle = angle;
+
+			} else if ( ! _this.staticMoving && _lastAngle ) {
+
+				_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
+				_eye.copy( _this.object.position ).sub( _this.target );
+				quaternion.setFromAxisAngle( _lastAxis, _lastAngle );
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
+
+			}
+
+			_movePrev.copy( _moveCurr );
+
+		};
+
+	}() );
+
+
+	this.zoomCamera = function () {
+
+		var factor;
+
+		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
+
+			factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
+			_touchZoomDistanceStart = _touchZoomDistanceEnd;
+			_eye.multiplyScalar( factor );
+
+		} else {
+
+			factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
+
+			if ( factor !== 1.0 && factor > 0.0 ) {
+
+				_eye.multiplyScalar( factor );
+
+			}
+
+			if ( _this.staticMoving ) {
+
+				_zoomStart.copy( _zoomEnd );
+
+			} else {
+
+				_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
+
+			}
+
+		}
+
+	};
+
+	this.panCamera = ( function() {
+
+		var mouseChange = new THREE.Vector2(),
+			objectUp = new THREE.Vector3(),
+			pan = new THREE.Vector3();
+
+		return function panCamera() {
+
+			mouseChange.copy( _panEnd ).sub( _panStart );
+
+			if ( mouseChange.lengthSq() ) {
+
+				mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
+
+				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
+				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
+
+				_this.object.position.add( pan );
+				_this.target.add( pan );
+
+				if ( _this.staticMoving ) {
+
+					_panStart.copy( _panEnd );
+
+				} else {
+
+					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+
+				}
+
+			}
+
+		};
+
+	}() );
+
+	this.checkDistances = function () {
+
+		if ( ! _this.noZoom || ! _this.noPan ) {
+
+			if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
+
+				_this.object.position.addVectors( _this.target, _eye.setLength( _this.maxDistance ) );
+				_zoomStart.copy( _zoomEnd );
+
+			}
+
+			if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
+
+				_this.object.position.addVectors( _this.target, _eye.setLength( _this.minDistance ) );
+				_zoomStart.copy( _zoomEnd );
+
+			}
+
+		}
+
+	};
+
+	this.update = function () {
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		if ( ! _this.noRotate ) {
+
+			_this.rotateCamera();
+
+		}
+
+		if ( ! _this.noZoom ) {
+
+			_this.zoomCamera();
+
+		}
+
+		if ( ! _this.noPan ) {
+
+			_this.panCamera();
+
+		}
+
+		_this.object.position.addVectors( _this.target, _eye );
+
+		_this.checkDistances();
+
+		_this.object.lookAt( _this.target );
+
+		if ( lastPosition.distanceToSquared( _this.object.position ) > EPS ) {
+
+			_this.dispatchEvent( changeEvent );
+
+			lastPosition.copy( _this.object.position );
+
+		}
+
+	};
+
+	this.reset = function () {
+
+		_state = STATE.NONE;
+		_prevState = STATE.NONE;
+
+		_this.target.copy( _this.target0 );
+		_this.object.position.copy( _this.position0 );
+		_this.object.up.copy( _this.up0 );
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		_this.object.lookAt( _this.target );
+
+		_this.dispatchEvent( changeEvent );
+
+		lastPosition.copy( _this.object.position );
+
+	};
+
+	// listeners
+
+	function keydown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		window.removeEventListener( 'keydown', keydown );
+
+		_prevState = _state;
+
+		if ( _state !== STATE.NONE ) {
+
+			return;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
+
+			_state = STATE.ROTATE;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
+
+			_state = STATE.ZOOM;
+
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
+
+			_state = STATE.PAN;
+
+		}
+
+	}
+
+	function keyup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		_state = _prevState;
+
+		window.addEventListener( 'keydown', keydown, false );
+
+	}
+
+	function mousedown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.NONE ) {
+
+			_state = event.button;
+
+		}
+
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
+
+			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
+			_movePrev.copy( _moveCurr );
+
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
+
+			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_zoomEnd.copy( _zoomStart );
+
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
+
+			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+			_panEnd.copy( _panStart );
+
+		}
+
+		document.addEventListener( 'mousemove', mousemove, false );
+		document.addEventListener( 'mouseup', mouseup, false );
+
+		_this.dispatchEvent( startEvent );
+
+	}
+
+	function mousemove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
+
+			_movePrev.copy( _moveCurr );
+			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
+
+			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
+
+			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
+
+		}
+
+	}
+
+	function mouseup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		_state = STATE.NONE;
+
+		document.removeEventListener( 'mousemove', mousemove );
+		document.removeEventListener( 'mouseup', mouseup );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function mousewheel( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.deltaMode ) {
+
+                        case 2:
+                                // Zoom in pages
+                                _zoomStart.y -= event.deltaY * 0.025;
+                                break;
+
+			case 1:
+                                // Zoom in lines
+				_zoomStart.y -= event.deltaY * 0.01;
+				break;
+
+			default:
+				// undefined, 0, assume pixels
+				_zoomStart.y -= event.deltaY * 0.00025;
+				break;
+
+		}
+
+		_this.dispatchEvent( startEvent );
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function touchstart( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_state = STATE.TOUCH_ROTATE;
+				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_movePrev.copy( _moveCurr );
+				break;
+
+			default: // 2 or more
+				_state = STATE.TOUCH_ZOOM_PAN;
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panStart.copy( getMouseOnScreen( x, y ) );
+				_panEnd.copy( _panStart );
+				break;
+
+		}
+
+		_this.dispatchEvent( startEvent );
+
+	}
+
+	function touchmove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_movePrev.copy( _moveCurr );
+				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				break;
+
+			default: // 2 or more
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
+
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				break;
+
+		}
+
+	}
+
+	function touchend( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 0:
+				_state = STATE.NONE;
+				break;
+
+			case 1:
+				_state = STATE.TOUCH_ROTATE;
+				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_movePrev.copy( _moveCurr );
+				break;
+
+		}
+
+		_this.dispatchEvent( endEvent );
+
+	}
+
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'wheel', mousewheel, false );
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
+
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	};
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
+	this.domElement.addEventListener( 'wheel', mousewheel, false );
+
+	this.domElement.addEventListener( 'touchstart', touchstart, false );
+	this.domElement.addEventListener( 'touchend', touchend, false );
+	this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+	window.addEventListener( 'keydown', keydown, false );
+	window.addEventListener( 'keyup', keyup, false );
+
+	this.handleResize();
+
+	// force an update at start
+	this.update();
+
+};
+
+THREE.TrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.TrackballControls.prototype.constructor = THREE.TrackballControls;

+ 1159 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/TransformControls.js

@@ -0,0 +1,1159 @@
+/**
+ * @author arodic / https://github.com/arodic
+ */
+
+( function () {
+
+	'use strict';
+
+	var GizmoMaterial = function ( parameters ) {
+
+		THREE.MeshBasicMaterial.call( this );
+
+		this.depthTest = false;
+		this.depthWrite = false;
+		this.side = THREE.FrontSide;
+		this.transparent = true;
+
+		this.setValues( parameters );
+
+		this.oldColor = this.color.clone();
+		this.oldOpacity = this.opacity;
+
+		this.highlight = function( highlighted ) {
+
+			if ( highlighted ) {
+
+				this.color.setRGB( 1, 1, 0 );
+				this.opacity = 1;
+
+			} else {
+
+				this.color.copy( this.oldColor );
+				this.opacity = this.oldOpacity;
+
+			}
+
+		};
+
+	};
+
+	GizmoMaterial.prototype = Object.create( THREE.MeshBasicMaterial.prototype );
+	GizmoMaterial.prototype.constructor = GizmoMaterial;
+
+
+	var GizmoLineMaterial = function ( parameters ) {
+
+		THREE.LineBasicMaterial.call( this );
+
+		this.depthTest = false;
+		this.depthWrite = false;
+		this.transparent = true;
+		this.linewidth = 1;
+
+		this.setValues( parameters );
+
+		this.oldColor = this.color.clone();
+		this.oldOpacity = this.opacity;
+
+		this.highlight = function( highlighted ) {
+
+			if ( highlighted ) {
+
+				this.color.setRGB( 1, 1, 0 );
+				this.opacity = 1;
+
+			} else {
+
+				this.color.copy( this.oldColor );
+				this.opacity = this.oldOpacity;
+
+			}
+
+		};
+
+	};
+
+	GizmoLineMaterial.prototype = Object.create( THREE.LineBasicMaterial.prototype );
+	GizmoLineMaterial.prototype.constructor = GizmoLineMaterial;
+
+
+	var pickerMaterial = new GizmoMaterial( { visible: false, transparent: false } );
+
+
+	THREE.TransformGizmo = function () {
+
+		var scope = this;
+
+		this.init = function () {
+
+			THREE.Object3D.call( this );
+
+			this.handles = new THREE.Object3D();
+			this.pickers = new THREE.Object3D();
+			this.planes = new THREE.Object3D();
+
+			this.add( this.handles );
+			this.add( this.pickers );
+			this.add( this.planes );
+
+			//// PLANES
+
+			var planeGeometry = new THREE.PlaneBufferGeometry( 50, 50, 2, 2 );
+			var planeMaterial = new THREE.MeshBasicMaterial( { visible: false, side: THREE.DoubleSide } );
+
+			var planes = {
+				"XY":   new THREE.Mesh( planeGeometry, planeMaterial ),
+				"YZ":   new THREE.Mesh( planeGeometry, planeMaterial ),
+				"XZ":   new THREE.Mesh( planeGeometry, planeMaterial ),
+				"XYZE": new THREE.Mesh( planeGeometry, planeMaterial )
+			};
+
+			this.activePlane = planes[ "XYZE" ];
+
+			planes[ "YZ" ].rotation.set( 0, Math.PI / 2, 0 );
+			planes[ "XZ" ].rotation.set( - Math.PI / 2, 0, 0 );
+
+			for ( var i in planes ) {
+
+				planes[ i ].name = i;
+				this.planes.add( planes[ i ] );
+				this.planes[ i ] = planes[ i ];
+
+			}
+
+			//// HANDLES AND PICKERS
+
+			var setupGizmos = function( gizmoMap, parent ) {
+
+				for ( var name in gizmoMap ) {
+
+					for ( i = gizmoMap[ name ].length; i --; ) {
+
+						var object = gizmoMap[ name ][ i ][ 0 ];
+						var position = gizmoMap[ name ][ i ][ 1 ];
+						var rotation = gizmoMap[ name ][ i ][ 2 ];
+
+						object.name = name;
+
+						if ( position ) object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
+						if ( rotation ) object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
+
+						parent.add( object );
+
+					}
+
+				}
+
+			};
+
+			setupGizmos( this.handleGizmos, this.handles );
+			setupGizmos( this.pickerGizmos, this.pickers );
+
+			// reset Transformations
+
+			this.traverse( function ( child ) {
+
+				if ( child instanceof THREE.Mesh ) {
+
+					child.updateMatrix();
+
+					var tempGeometry = child.geometry.clone();
+					tempGeometry.applyMatrix( child.matrix );
+					child.geometry = tempGeometry;
+
+					child.position.set( 0, 0, 0 );
+					child.rotation.set( 0, 0, 0 );
+					child.scale.set( 1, 1, 1 );
+
+				}
+
+			} );
+
+		};
+
+		this.highlight = function ( axis ) {
+
+			this.traverse( function( child ) {
+
+				if ( child.material && child.material.highlight ) {
+
+					if ( child.name === axis ) {
+
+						child.material.highlight( true );
+
+					} else {
+
+						child.material.highlight( false );
+
+					}
+
+				}
+
+			} );
+
+		};
+
+	};
+
+	THREE.TransformGizmo.prototype = Object.create( THREE.Object3D.prototype );
+	THREE.TransformGizmo.prototype.constructor = THREE.TransformGizmo;
+
+	THREE.TransformGizmo.prototype.update = function ( rotation, eye ) {
+
+		var vec1 = new THREE.Vector3( 0, 0, 0 );
+		var vec2 = new THREE.Vector3( 0, 1, 0 );
+		var lookAtMatrix = new THREE.Matrix4();
+
+		this.traverse( function( child ) {
+
+			if ( child.name.search( "E" ) !== - 1 ) {
+
+				child.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( eye, vec1, vec2 ) );
+
+			} else if ( child.name.search( "X" ) !== - 1 || child.name.search( "Y" ) !== - 1 || child.name.search( "Z" ) !== - 1 ) {
+
+				child.quaternion.setFromEuler( rotation );
+
+			}
+
+		} );
+
+	};
+
+	THREE.TransformGizmoTranslate = function () {
+
+		THREE.TransformGizmo.call( this );
+
+		var arrowGeometry = new THREE.Geometry();
+		var mesh = new THREE.Mesh( new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ) );
+		mesh.position.y = 0.5;
+		mesh.updateMatrix();
+
+		arrowGeometry.merge( mesh.geometry, mesh.matrix );
+
+		var lineXGeometry = new THREE.BufferGeometry();
+		lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  1, 0, 0 ], 3 ) );
+
+		var lineYGeometry = new THREE.BufferGeometry();
+		lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  0, 1, 0 ], 3 ) );
+
+		var lineZGeometry = new THREE.BufferGeometry();
+		lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  0, 0, 1 ], 3 ) );
+
+		this.handleGizmos = {
+
+			X: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
+				[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
+			],
+
+			Y: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x00ff00 } ) ), [ 0, 0.5, 0 ] ],
+				[	new THREE.Line( lineYGeometry, new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
+			],
+
+			Z: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x0000ff } ) ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ],
+				[ new THREE.Line( lineZGeometry, new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
+			],
+
+			XYZ: [
+				[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), new GizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) ), [ 0, 0, 0 ], [ 0, 0, 0 ] ]
+			],
+
+			XY: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ), [ 0.15, 0.15, 0 ] ]
+			],
+
+			YZ: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ), [ 0, 0.15, 0.15 ], [ 0, Math.PI / 2, 0 ] ]
+			],
+
+			XZ: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ] ]
+			]
+
+		};
+
+		this.pickerGizmos = {
+
+			X: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
+			],
+
+			Y: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0.6, 0 ] ]
+			],
+
+			Z: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ]
+			],
+
+			XYZ: [
+				[ new THREE.Mesh( new THREE.OctahedronGeometry( 0.2, 0 ), pickerMaterial ) ]
+			],
+
+			XY: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), pickerMaterial ), [ 0.2, 0.2, 0 ] ]
+			],
+
+			YZ: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), pickerMaterial ), [ 0, 0.2, 0.2 ], [ 0, Math.PI / 2, 0 ] ]
+			],
+
+			XZ: [
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), pickerMaterial ), [ 0.2, 0, 0.2 ], [ - Math.PI / 2, 0, 0 ] ]
+			]
+
+		};
+
+		this.setActivePlane = function ( axis, eye ) {
+
+			var tempMatrix = new THREE.Matrix4();
+			eye.applyMatrix4( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
+
+			if ( axis === "X" ) {
+
+				this.activePlane = this.planes[ "XY" ];
+
+				if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
+
+			}
+
+			if ( axis === "Y" ) {
+
+				this.activePlane = this.planes[ "XY" ];
+
+				if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
+
+			}
+
+			if ( axis === "Z" ) {
+
+				this.activePlane = this.planes[ "XZ" ];
+
+				if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
+
+			}
+
+			if ( axis === "XYZ" ) this.activePlane = this.planes[ "XYZE" ];
+
+			if ( axis === "XY" ) this.activePlane = this.planes[ "XY" ];
+
+			if ( axis === "YZ" ) this.activePlane = this.planes[ "YZ" ];
+
+			if ( axis === "XZ" ) this.activePlane = this.planes[ "XZ" ];
+
+		};
+
+		this.init();
+
+	};
+
+	THREE.TransformGizmoTranslate.prototype = Object.create( THREE.TransformGizmo.prototype );
+	THREE.TransformGizmoTranslate.prototype.constructor = THREE.TransformGizmoTranslate;
+
+	THREE.TransformGizmoRotate = function () {
+
+		THREE.TransformGizmo.call( this );
+
+		var CircleGeometry = function ( radius, facing, arc ) {
+
+			var geometry = new THREE.BufferGeometry();
+			var vertices = [];
+			arc = arc ? arc : 1;
+
+			for ( var i = 0; i <= 64 * arc; ++ i ) {
+
+				if ( facing === 'x' ) vertices.push( 0, Math.cos( i / 32 * Math.PI ) * radius, Math.sin( i / 32 * Math.PI ) * radius );
+				if ( facing === 'y' ) vertices.push( Math.cos( i / 32 * Math.PI ) * radius, 0, Math.sin( i / 32 * Math.PI ) * radius );
+				if ( facing === 'z' ) vertices.push( Math.sin( i / 32 * Math.PI ) * radius, Math.cos( i / 32 * Math.PI ) * radius, 0 );
+
+			}
+
+			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
+			return geometry;
+
+		};
+
+		this.handleGizmos = {
+
+			X: [
+				[ new THREE.Line( new CircleGeometry( 1, 'x', 0.5 ), new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
+			],
+
+			Y: [
+				[ new THREE.Line( new CircleGeometry( 1, 'y', 0.5 ), new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
+			],
+
+			Z: [
+				[ new THREE.Line( new CircleGeometry( 1, 'z', 0.5 ), new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
+			],
+
+			E: [
+				[ new THREE.Line( new CircleGeometry( 1.25, 'z', 1 ), new GizmoLineMaterial( { color: 0xcccc00 } ) ) ]
+			],
+
+			XYZE: [
+				[ new THREE.Line( new CircleGeometry( 1, 'z', 1 ), new GizmoLineMaterial( { color: 0x787878 } ) ) ]
+			]
+
+		};
+
+		this.pickerGizmos = {
+
+			X: [
+				[ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ] ]
+			],
+
+			Y: [
+				[ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ Math.PI / 2, 0, 0 ] ]
+			],
+
+			Z: [
+				[ new THREE.Mesh( new THREE.TorusBufferGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
+			],
+
+			E: [
+				[ new THREE.Mesh( new THREE.TorusBufferGeometry( 1.25, 0.12, 2, 24 ), pickerMaterial ) ]
+			],
+
+			XYZE: [
+				[ new THREE.Mesh() ]// TODO
+			]
+
+		};
+
+		this.setActivePlane = function ( axis ) {
+
+			if ( axis === "E" ) this.activePlane = this.planes[ "XYZE" ];
+
+			if ( axis === "X" ) this.activePlane = this.planes[ "YZ" ];
+
+			if ( axis === "Y" ) this.activePlane = this.planes[ "XZ" ];
+
+			if ( axis === "Z" ) this.activePlane = this.planes[ "XY" ];
+
+		};
+
+		this.update = function ( rotation, eye2 ) {
+
+			THREE.TransformGizmo.prototype.update.apply( this, arguments );
+
+			var group = {
+
+				handles: this[ "handles" ],
+				pickers: this[ "pickers" ]
+
+			};
+
+			var tempMatrix = new THREE.Matrix4();
+			var worldRotation = new THREE.Euler( 0, 0, 1 );
+			var tempQuaternion = new THREE.Quaternion();
+			var unitX = new THREE.Vector3( 1, 0, 0 );
+			var unitY = new THREE.Vector3( 0, 1, 0 );
+			var unitZ = new THREE.Vector3( 0, 0, 1 );
+			var quaternionX = new THREE.Quaternion();
+			var quaternionY = new THREE.Quaternion();
+			var quaternionZ = new THREE.Quaternion();
+			var eye = eye2.clone();
+
+			worldRotation.copy( this.planes[ "XY" ].rotation );
+			tempQuaternion.setFromEuler( worldRotation );
+
+			tempMatrix.makeRotationFromQuaternion( tempQuaternion ).getInverse( tempMatrix );
+			eye.applyMatrix4( tempMatrix );
+
+			this.traverse( function( child ) {
+
+				tempQuaternion.setFromEuler( worldRotation );
+
+				if ( child.name === "X" ) {
+
+					quaternionX.setFromAxisAngle( unitX, Math.atan2( - eye.y, eye.z ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					child.quaternion.copy( tempQuaternion );
+
+				}
+
+				if ( child.name === "Y" ) {
+
+					quaternionY.setFromAxisAngle( unitY, Math.atan2( eye.x, eye.z ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
+					child.quaternion.copy( tempQuaternion );
+
+				}
+
+				if ( child.name === "Z" ) {
+
+					quaternionZ.setFromAxisAngle( unitZ, Math.atan2( eye.y, eye.x ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
+					child.quaternion.copy( tempQuaternion );
+
+				}
+
+			} );
+
+		};
+
+		this.init();
+
+	};
+
+	THREE.TransformGizmoRotate.prototype = Object.create( THREE.TransformGizmo.prototype );
+	THREE.TransformGizmoRotate.prototype.constructor = THREE.TransformGizmoRotate;
+
+	THREE.TransformGizmoScale = function () {
+
+		THREE.TransformGizmo.call( this );
+
+		var arrowGeometry = new THREE.Geometry();
+		var mesh = new THREE.Mesh( new THREE.BoxGeometry( 0.125, 0.125, 0.125 ) );
+		mesh.position.y = 0.5;
+		mesh.updateMatrix();
+
+		arrowGeometry.merge( mesh.geometry, mesh.matrix );
+
+		var lineXGeometry = new THREE.BufferGeometry();
+		lineXGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  1, 0, 0 ], 3 ) );
+
+		var lineYGeometry = new THREE.BufferGeometry();
+		lineYGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  0, 1, 0 ], 3 ) );
+
+		var lineZGeometry = new THREE.BufferGeometry();
+		lineZGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0,  0, 0, 1 ], 3 ) );
+
+		this.handleGizmos = {
+
+			X: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
+				[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
+			],
+
+			Y: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x00ff00 } ) ), [ 0, 0.5, 0 ] ],
+				[ new THREE.Line( lineYGeometry, new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
+			],
+
+			Z: [
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0x0000ff } ) ), [ 0, 0, 0.5 ], [ Math.PI / 2, 0, 0 ] ],
+				[ new THREE.Line( lineZGeometry, new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
+			],
+
+			XYZ: [
+				[ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.125, 0.125, 0.125 ), new GizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) ) ]
+			]
+
+		};
+
+		this.pickerGizmos = {
+
+			X: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
+			],
+
+			Y: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0.6, 0 ] ]
+			],
+
+			Z: [
+				[ new THREE.Mesh( new THREE.CylinderBufferGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0, 0, 0.6 ], [ Math.PI / 2, 0, 0 ] ]
+			],
+
+			XYZ: [
+				[ new THREE.Mesh( new THREE.BoxBufferGeometry( 0.4, 0.4, 0.4 ), pickerMaterial ) ]
+			]
+
+		};
+
+		this.setActivePlane = function ( axis, eye ) {
+
+			var tempMatrix = new THREE.Matrix4();
+			eye.applyMatrix4( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
+
+			if ( axis === "X" ) {
+
+				this.activePlane = this.planes[ "XY" ];
+				if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
+
+			}
+
+			if ( axis === "Y" ) {
+
+				this.activePlane = this.planes[ "XY" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
+
+			}
+
+			if ( axis === "Z" ) {
+
+				this.activePlane = this.planes[ "XZ" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
+
+			}
+
+			if ( axis === "XYZ" ) this.activePlane = this.planes[ "XYZE" ];
+
+		};
+
+		this.init();
+
+	};
+
+	THREE.TransformGizmoScale.prototype = Object.create( THREE.TransformGizmo.prototype );
+	THREE.TransformGizmoScale.prototype.constructor = THREE.TransformGizmoScale;
+
+	THREE.TransformControls = function ( camera, domElement ) {
+
+		// TODO: Make non-uniform scale and rotate play nice in hierarchies
+		// TODO: ADD RXYZ contol
+
+		THREE.Object3D.call( this );
+
+		domElement = ( domElement !== undefined ) ? domElement : document;
+
+		this.object = undefined;
+		this.visible = false;
+		this.translationSnap = null;
+		this.rotationSnap = null;
+		this.space = "world";
+		this.size = 1;
+		this.axis = null;
+
+		var scope = this;
+
+		var _mode = "translate";
+		var _dragging = false;
+		var _plane = "XY";
+		var _gizmo = {
+
+			"translate": new THREE.TransformGizmoTranslate(),
+			"rotate": new THREE.TransformGizmoRotate(),
+			"scale": new THREE.TransformGizmoScale()
+		};
+
+		for ( var type in _gizmo ) {
+
+			var gizmoObj = _gizmo[ type ];
+
+			gizmoObj.visible = ( type === _mode );
+			this.add( gizmoObj );
+
+		}
+
+		var changeEvent = { type: "change" };
+		var mouseDownEvent = { type: "mouseDown" };
+		var mouseUpEvent = { type: "mouseUp", mode: _mode };
+		var objectChangeEvent = { type: "objectChange" };
+
+		var ray = new THREE.Raycaster();
+		var pointerVector = new THREE.Vector2();
+
+		var point = new THREE.Vector3();
+		var offset = new THREE.Vector3();
+
+		var rotation = new THREE.Vector3();
+		var offsetRotation = new THREE.Vector3();
+		var scale = 1;
+
+		var lookAtMatrix = new THREE.Matrix4();
+		var eye = new THREE.Vector3();
+
+		var tempMatrix = new THREE.Matrix4();
+		var tempVector = new THREE.Vector3();
+		var tempQuaternion = new THREE.Quaternion();
+		var unitX = new THREE.Vector3( 1, 0, 0 );
+		var unitY = new THREE.Vector3( 0, 1, 0 );
+		var unitZ = new THREE.Vector3( 0, 0, 1 );
+
+		var quaternionXYZ = new THREE.Quaternion();
+		var quaternionX = new THREE.Quaternion();
+		var quaternionY = new THREE.Quaternion();
+		var quaternionZ = new THREE.Quaternion();
+		var quaternionE = new THREE.Quaternion();
+
+		var oldPosition = new THREE.Vector3();
+		var oldScale = new THREE.Vector3();
+		var oldRotationMatrix = new THREE.Matrix4();
+
+		var parentRotationMatrix  = new THREE.Matrix4();
+		var parentScale = new THREE.Vector3();
+
+		var worldPosition = new THREE.Vector3();
+		var worldRotation = new THREE.Euler();
+		var worldRotationMatrix  = new THREE.Matrix4();
+		var camPosition = new THREE.Vector3();
+		var camRotation = new THREE.Euler();
+
+		domElement.addEventListener( "mousedown", onPointerDown, false );
+		domElement.addEventListener( "touchstart", onPointerDown, false );
+
+		domElement.addEventListener( "mousemove", onPointerHover, false );
+		domElement.addEventListener( "touchmove", onPointerHover, false );
+
+		domElement.addEventListener( "mousemove", onPointerMove, false );
+		domElement.addEventListener( "touchmove", onPointerMove, false );
+
+		domElement.addEventListener( "mouseup", onPointerUp, false );
+		domElement.addEventListener( "mouseout", onPointerUp, false );
+		domElement.addEventListener( "touchend", onPointerUp, false );
+		domElement.addEventListener( "touchcancel", onPointerUp, false );
+		domElement.addEventListener( "touchleave", onPointerUp, false );
+
+		this.dispose = function () {
+
+			domElement.removeEventListener( "mousedown", onPointerDown );
+			domElement.removeEventListener( "touchstart", onPointerDown );
+
+			domElement.removeEventListener( "mousemove", onPointerHover );
+			domElement.removeEventListener( "touchmove", onPointerHover );
+
+			domElement.removeEventListener( "mousemove", onPointerMove );
+			domElement.removeEventListener( "touchmove", onPointerMove );
+
+			domElement.removeEventListener( "mouseup", onPointerUp );
+			domElement.removeEventListener( "mouseout", onPointerUp );
+			domElement.removeEventListener( "touchend", onPointerUp );
+			domElement.removeEventListener( "touchcancel", onPointerUp );
+			domElement.removeEventListener( "touchleave", onPointerUp );
+
+		};
+
+		this.attach = function ( object ) {
+
+			this.object = object;
+			this.visible = true;
+			this.update();
+
+		};
+
+		this.detach = function () {
+
+			this.object = undefined;
+			this.visible = false;
+			this.axis = null;
+
+		};
+
+		this.getMode = function () {
+
+			return _mode;
+
+		};
+
+		this.setMode = function ( mode ) {
+
+			_mode = mode ? mode : _mode;
+
+			if ( _mode === "scale" ) scope.space = "local";
+
+			for ( var type in _gizmo ) _gizmo[ type ].visible = ( type === _mode );
+
+			this.update();
+			scope.dispatchEvent( changeEvent );
+
+		};
+
+		this.setTranslationSnap = function ( translationSnap ) {
+
+			scope.translationSnap = translationSnap;
+
+		};
+
+		this.setRotationSnap = function ( rotationSnap ) {
+
+			scope.rotationSnap = rotationSnap;
+
+		};
+
+		this.setSize = function ( size ) {
+
+			scope.size = size;
+			this.update();
+			scope.dispatchEvent( changeEvent );
+
+		};
+
+		this.setSpace = function ( space ) {
+
+			scope.space = space;
+			this.update();
+			scope.dispatchEvent( changeEvent );
+
+		};
+
+		this.update = function () {
+
+			if ( scope.object === undefined ) return;
+
+			scope.object.updateMatrixWorld();
+			worldPosition.setFromMatrixPosition( scope.object.matrixWorld );
+			worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
+
+			camera.updateMatrixWorld();
+			camPosition.setFromMatrixPosition( camera.matrixWorld );
+			camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
+
+			scale = worldPosition.distanceTo( camPosition ) / 6 * scope.size;
+			this.position.copy( worldPosition );
+			this.scale.set( scale, scale, scale );
+
+			if ( camera instanceof THREE.PerspectiveCamera ) {
+
+				eye.copy( camPosition ).sub( worldPosition ).normalize();
+
+			} else if ( camera instanceof THREE.OrthographicCamera ) {
+
+				eye.copy( camPosition ).normalize();
+
+			}
+
+			if ( scope.space === "local" ) {
+
+				_gizmo[ _mode ].update( worldRotation, eye );
+
+			} else if ( scope.space === "world" ) {
+
+				_gizmo[ _mode ].update( new THREE.Euler(), eye );
+
+			}
+
+			_gizmo[ _mode ].highlight( scope.axis );
+
+		};
+
+		function onPointerHover( event ) {
+
+			if ( scope.object === undefined || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
+
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
+
+			var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
+
+			var axis = null;
+
+			if ( intersect ) {
+
+				axis = intersect.object.name;
+
+				event.preventDefault();
+
+			}
+
+			if ( scope.axis !== axis ) {
+
+				scope.axis = axis;
+				scope.update();
+				scope.dispatchEvent( changeEvent );
+
+			}
+
+		}
+
+		function onPointerDown( event ) {
+
+			if ( scope.object === undefined || _dragging === true || ( event.button !== undefined && event.button !== 0 ) ) return;
+
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
+
+			if ( pointer.button === 0 || pointer.button === undefined ) {
+
+				var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
+
+				if ( intersect ) {
+
+					event.preventDefault();
+					event.stopPropagation();
+
+					scope.dispatchEvent( mouseDownEvent );
+
+					scope.axis = intersect.object.name;
+
+					scope.update();
+
+					eye.copy( camPosition ).sub( worldPosition ).normalize();
+
+					_gizmo[ _mode ].setActivePlane( scope.axis, eye );
+
+					var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
+
+					if ( planeIntersect ) {
+
+						oldPosition.copy( scope.object.position );
+						oldScale.copy( scope.object.scale );
+
+						oldRotationMatrix.extractRotation( scope.object.matrix );
+						worldRotationMatrix.extractRotation( scope.object.matrixWorld );
+
+						parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
+						parentScale.setFromMatrixScale( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
+
+						offset.copy( planeIntersect.point );
+
+					}
+
+				}
+
+			}
+
+			_dragging = true;
+
+		}
+
+		function onPointerMove( event ) {
+
+			if ( scope.object === undefined || scope.axis === null || _dragging === false || ( event.button !== undefined && event.button !== 0 ) ) return;
+
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
+
+			var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
+
+			if ( planeIntersect === false ) return;
+
+			event.preventDefault();
+			event.stopPropagation();
+
+			point.copy( planeIntersect.point );
+
+			if ( _mode === "translate" ) {
+
+				point.sub( offset );
+				point.multiply( parentScale );
+
+				if ( scope.space === "local" ) {
+
+					point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+					if ( scope.axis.search( "X" ) === - 1 ) point.x = 0;
+					if ( scope.axis.search( "Y" ) === - 1 ) point.y = 0;
+					if ( scope.axis.search( "Z" ) === - 1 ) point.z = 0;
+
+					point.applyMatrix4( oldRotationMatrix );
+
+					scope.object.position.copy( oldPosition );
+					scope.object.position.add( point );
+
+				}
+
+				if ( scope.space === "world" || scope.axis.search( "XYZ" ) !== - 1 ) {
+
+					if ( scope.axis.search( "X" ) === - 1 ) point.x = 0;
+					if ( scope.axis.search( "Y" ) === - 1 ) point.y = 0;
+					if ( scope.axis.search( "Z" ) === - 1 ) point.z = 0;
+
+					point.applyMatrix4( tempMatrix.getInverse( parentRotationMatrix ) );
+
+					scope.object.position.copy( oldPosition );
+					scope.object.position.add( point );
+
+				}
+
+				if ( scope.translationSnap !== null ) {
+
+					if ( scope.space === "local" ) {
+
+						scope.object.position.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+					}
+
+					if ( scope.axis.search( "X" ) !== - 1 ) scope.object.position.x = Math.round( scope.object.position.x / scope.translationSnap ) * scope.translationSnap;
+					if ( scope.axis.search( "Y" ) !== - 1 ) scope.object.position.y = Math.round( scope.object.position.y / scope.translationSnap ) * scope.translationSnap;
+					if ( scope.axis.search( "Z" ) !== - 1 ) scope.object.position.z = Math.round( scope.object.position.z / scope.translationSnap ) * scope.translationSnap;
+
+					if ( scope.space === "local" ) {
+
+						scope.object.position.applyMatrix4( worldRotationMatrix );
+
+					}
+
+				}
+
+			} else if ( _mode === "scale" ) {
+
+				point.sub( offset );
+				point.multiply( parentScale );
+
+				if ( scope.space === "local" ) {
+
+					if ( scope.axis === "XYZ" ) {
+
+						scale = 1 + ( ( point.y ) / Math.max( oldScale.x, oldScale.y, oldScale.z ) );
+
+						scope.object.scale.x = oldScale.x * scale;
+						scope.object.scale.y = oldScale.y * scale;
+						scope.object.scale.z = oldScale.z * scale;
+
+					} else {
+
+						point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+						if ( scope.axis === "X" ) scope.object.scale.x = oldScale.x * ( 1 + point.x / oldScale.x );
+						if ( scope.axis === "Y" ) scope.object.scale.y = oldScale.y * ( 1 + point.y / oldScale.y );
+						if ( scope.axis === "Z" ) scope.object.scale.z = oldScale.z * ( 1 + point.z / oldScale.z );
+
+					}
+
+				}
+
+			} else if ( _mode === "rotate" ) {
+
+				point.sub( worldPosition );
+				point.multiply( parentScale );
+				tempVector.copy( offset ).sub( worldPosition );
+				tempVector.multiply( parentScale );
+
+				if ( scope.axis === "E" ) {
+
+					point.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
+					tempVector.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
+
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+
+					quaternionE.setFromAxisAngle( eye, rotation.z - offsetRotation.z );
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionE );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+
+					scope.object.quaternion.copy( tempQuaternion );
+
+				} else if ( scope.axis === "XYZE" ) {
+
+					quaternionE.setFromEuler( point.clone().cross( tempVector ).normalize() ); // rotation axis
+
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+					quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo( tempVector ) );
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+
+					scope.object.quaternion.copy( tempQuaternion );
+
+				} else if ( scope.space === "local" ) {
+
+					point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+					tempVector.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+
+					quaternionXYZ.setFromRotationMatrix( oldRotationMatrix );
+
+					if ( scope.rotationSnap !== null ) {
+
+						quaternionX.setFromAxisAngle( unitX, Math.round( ( rotation.x - offsetRotation.x ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionY.setFromAxisAngle( unitY, Math.round( ( rotation.y - offsetRotation.y ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionZ.setFromAxisAngle( unitZ, Math.round( ( rotation.z - offsetRotation.z ) / scope.rotationSnap ) * scope.rotationSnap );
+
+					} else {
+
+						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+
+					}
+
+					if ( scope.axis === "X" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionX );
+					if ( scope.axis === "Y" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionY );
+					if ( scope.axis === "Z" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionZ );
+
+					scope.object.quaternion.copy( quaternionXYZ );
+
+				} else if ( scope.space === "world" ) {
+
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+
+					if ( scope.rotationSnap !== null ) {
+
+						quaternionX.setFromAxisAngle( unitX, Math.round( ( rotation.x - offsetRotation.x ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionY.setFromAxisAngle( unitY, Math.round( ( rotation.y - offsetRotation.y ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionZ.setFromAxisAngle( unitZ, Math.round( ( rotation.z - offsetRotation.z ) / scope.rotationSnap ) * scope.rotationSnap );
+
+					} else {
+
+						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+
+					}
+
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+
+					if ( scope.axis === "X" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					if ( scope.axis === "Y" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
+					if ( scope.axis === "Z" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
+
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+
+					scope.object.quaternion.copy( tempQuaternion );
+
+				}
+
+			}
+
+			scope.update();
+			scope.dispatchEvent( changeEvent );
+			scope.dispatchEvent( objectChangeEvent );
+
+		}
+
+		function onPointerUp( event ) {
+
+			event.preventDefault(); // Prevent MouseEvent on mobile
+
+			if ( event.button !== undefined && event.button !== 0 ) return;
+
+			if ( _dragging && ( scope.axis !== null ) ) {
+
+				mouseUpEvent.mode = _mode;
+				scope.dispatchEvent( mouseUpEvent );
+
+			}
+
+			_dragging = false;
+
+			if ( 'TouchEvent' in window && event instanceof TouchEvent ) {
+
+				// Force "rollover"
+
+				scope.axis = null;
+				scope.update();
+				scope.dispatchEvent( changeEvent );
+
+			} else {
+
+				onPointerHover( event );
+
+			}
+
+		}
+
+		function intersectObjects( pointer, objects ) {
+
+			var rect = domElement.getBoundingClientRect();
+			var x = ( pointer.clientX - rect.left ) / rect.width;
+			var y = ( pointer.clientY - rect.top ) / rect.height;
+
+			pointerVector.set( ( x * 2 ) - 1, - ( y * 2 ) + 1 );
+			ray.setFromCamera( pointerVector, camera );
+
+			var intersections = ray.intersectObjects( objects, true );
+			return intersections[ 0 ] ? intersections[ 0 ] : false;
+
+		}
+
+	};
+
+	THREE.TransformControls.prototype = Object.create( THREE.Object3D.prototype );
+	THREE.TransformControls.prototype.constructor = THREE.TransformControls;
+
+}() );

+ 173 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/controls/VRControls.js

@@ -0,0 +1,173 @@
+/**
+ * @author dmarcos / https://github.com/dmarcos
+ * @author mrdoob / http://mrdoob.com
+ */
+
+THREE.VRControls = function ( object, onError ) {
+
+	var scope = this;
+
+	var vrDisplay, vrDisplays;
+
+	var standingMatrix = new THREE.Matrix4();
+
+	var frameData = null;
+
+	if ( 'VRFrameData' in window ) {
+
+		frameData = new VRFrameData();
+
+	}
+
+	function gotVRDisplays( displays ) {
+
+		vrDisplays = displays;
+
+		if ( displays.length > 0 ) {
+
+			vrDisplay = displays[ 0 ];
+
+		} else {
+
+			if ( onError ) onError( 'VR input not available.' );
+
+		}
+
+	}
+
+	if ( navigator.getVRDisplays ) {
+
+		navigator.getVRDisplays().then( gotVRDisplays ).catch ( function () {
+
+			console.warn( 'THREE.VRControls: Unable to get VR Displays' );
+
+		} );
+
+	}
+
+	// the Rift SDK returns the position in meters
+	// this scale factor allows the user to define how meters
+	// are converted to scene units.
+
+	this.scale = 1;
+
+	// If true will use "standing space" coordinate system where y=0 is the
+	// floor and x=0, z=0 is the center of the room.
+	this.standing = false;
+
+	// Distance from the users eyes to the floor in meters. Used when
+	// standing=true but the VRDisplay doesn't provide stageParameters.
+	this.userHeight = 1.6;
+
+	this.getVRDisplay = function () {
+
+		return vrDisplay;
+
+	};
+
+	this.setVRDisplay = function ( value ) {
+
+		vrDisplay = value;
+
+	};
+
+	this.getVRDisplays = function () {
+
+		console.warn( 'THREE.VRControls: getVRDisplays() is being deprecated.' );
+		return vrDisplays;
+
+	};
+
+	this.getStandingMatrix = function () {
+
+		return standingMatrix;
+
+	};
+
+	this.update = function () {
+
+		if ( vrDisplay ) {
+
+			var pose;
+
+			if ( vrDisplay.getFrameData ) {
+
+				vrDisplay.getFrameData( frameData );
+				pose = frameData.pose;
+
+			} else if ( vrDisplay.getPose ) {
+
+				pose = vrDisplay.getPose();
+
+			}
+
+			if ( pose.orientation !== null ) {
+
+				object.quaternion.fromArray( pose.orientation );
+
+			}
+
+			if ( pose.position !== null ) {
+
+				object.position.fromArray( pose.position );
+
+			} else {
+
+				object.position.set( 0, 0, 0 );
+
+			}
+
+			if ( this.standing ) {
+
+				if ( vrDisplay.stageParameters ) {
+
+					object.updateMatrix();
+
+					standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform );
+					object.applyMatrix( standingMatrix );
+
+				} else {
+
+					object.position.setY( object.position.y + this.userHeight );
+
+				}
+
+			}
+
+			object.position.multiplyScalar( scope.scale );
+
+		}
+
+	};
+
+	this.resetPose = function () {
+
+		if ( vrDisplay ) {
+
+			vrDisplay.resetPose();
+
+		}
+
+	};
+
+	this.resetSensor = function () {
+
+		console.warn( 'THREE.VRControls: .resetSensor() is now .resetPose().' );
+		this.resetPose();
+
+	};
+
+	this.zeroSensor = function () {
+
+		console.warn( 'THREE.VRControls: .zeroSensor() is now .resetPose().' );
+		this.resetPose();
+
+	};
+
+	this.dispose = function () {
+
+		vrDisplay = null;
+
+	};
+
+};

+ 39 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/gui.js

@@ -0,0 +1,39 @@
+var transitionParams = {
+	"useTexture": true,
+	"transition": 0.5,
+	"transitionSpeed": 2.0,
+	"texture": 5,
+	"loopTexture": true,
+	"animateTransition": true,
+	"textureThreshold": 0.3
+};
+
+function initGUI() {
+	
+	var gui = new dat.GUI();
+
+	gui.add( transitionParams, "useTexture" ).onChange( function( value ) {
+		
+		transition.useTexture( value );
+		
+	} );
+	
+	gui.add( transitionParams, 'loopTexture' );
+	
+	gui.add( transitionParams, 'texture', { Perlin: 0, Squares: 1, Cells: 2, Distort: 3, Gradient: 4, Radial: 5 } ).onChange( function( value ) {
+		
+		transition.setTexture( value );
+		
+	} ).listen();
+		
+	gui.add( transitionParams, "textureThreshold", 0, 1, 0.01 ).onChange( function( value ) {
+		
+		transition.setTextureThreshold( value );
+		
+	} );
+
+	gui.add( transitionParams, "animateTransition" );
+	gui.add( transitionParams, "transition", 0, 1, 0.01 ).listen();
+	gui.add( transitionParams, "transitionSpeed", 0.5, 5, 0.01 );
+	
+}

+ 111 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/scenes.js

@@ -0,0 +1,111 @@
+function generateGeometry( objectType, numObjects ) {
+
+	var geometry = new THREE.Geometry();
+
+	function applyVertexColors( g, c ) {
+
+		g.faces.forEach( function( f ) {
+
+			var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
+
+			for ( var j = 0; j < n; j ++ ) {
+
+				f.vertexColors[ j ] = c;
+
+			}
+
+		} );
+
+	}
+
+	for ( var i = 0; i < numObjects; i ++ ) {
+
+		var position = new THREE.Vector3();
+
+		position.x = Math.random() * 10000 - 5000;
+		position.y = Math.random() * 6000 - 3000;
+		position.z = Math.random() * 8000 - 4000;
+
+		var rotation = new THREE.Euler();
+
+		rotation.x = Math.random() * 2 * Math.PI;
+		rotation.y = Math.random() * 2 * Math.PI;
+		rotation.z = Math.random() * 2 * Math.PI;
+
+		var scale = new THREE.Vector3();
+
+		var geom, color = new THREE.Color();
+
+		scale.x = Math.random() * 200 + 100;
+
+		if ( objectType == "cube" ) {
+
+			geom = new THREE.BoxGeometry( 1, 1, 1 );
+			scale.y = Math.random() * 200 + 100;
+			scale.z = Math.random() * 200 + 100;
+			color.setRGB( 0, 0, Math.random() + 0.1 );
+
+		} else if ( objectType == "sphere" ) {
+
+			geom = new THREE.IcosahedronGeometry( 1, 1 );
+			scale.y = scale.z = scale.x;
+			color.setRGB( Math.random() + 0.1, 0, 0 );
+
+		}
+
+		// give the geom's vertices a random color, to be displayed
+		applyVertexColors( geom, color );
+
+		var mesh = new THREE.Mesh( geom );
+		mesh.position.copy( position );
+		mesh.rotation.copy( rotation );
+		mesh.scale.copy( scale );
+		mesh.updateMatrix();
+
+		geometry.merge( mesh.geometry, mesh.matrix );
+
+	}
+
+	return geometry;
+
+}
+
+function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
+
+	this.clearColor = clearColor;
+
+	this.camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 10000 );
+	this.camera.position.z = cameraZ;
+
+	// Setup scene
+	this.scene = new THREE.Scene();
+	this.scene.add( new THREE.AmbientLight( 0x555555 ) );
+
+	var light = new THREE.SpotLight( 0xffffff, 1.5 );
+	light.position.set( 0, 500, 2000 );
+	this.scene.add( light );
+
+	this.rotationSpeed = rotationSpeed;
+	defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } );
+	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
+	this.scene.add( this.mesh );
+
+	renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+	this.fbo = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
+
+	this.render = function( delta, rtt ) {
+
+		this.mesh.rotation.x += delta * this.rotationSpeed.x;
+		this.mesh.rotation.y += delta * this.rotationSpeed.y;
+		this.mesh.rotation.z += delta * this.rotationSpeed.z;
+
+		renderer.setClearColor( this.clearColor );
+
+		if ( rtt )
+			renderer.render( this.scene, this.camera, this.fbo, true );
+		else
+			renderer.render( this.scene, this.camera );
+
+	};
+
+}

+ 161 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/crossfade/transition.js

@@ -0,0 +1,161 @@
+function Transition ( sceneA, sceneB ) {
+
+	this.scene = new THREE.Scene();
+
+	this.cameraOrtho = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10, 10 );
+
+	this.textures = [];
+	for ( var i = 0; i < 6; i ++ )
+		this.textures[ i ] = new THREE.TextureLoader().load( 'textures/transition/transition' + ( i + 1 ) + '.png' );
+
+	this.quadmaterial = new THREE.ShaderMaterial( {
+
+		uniforms: {
+
+			tDiffuse1: {
+				value: null
+			},
+			tDiffuse2: {
+				value: null
+			},
+			mixRatio: {
+				value: 0.0
+			},
+			threshold: {
+				value: 0.1
+			},
+			useTexture: {
+				value: 1
+			},
+			tMixTexture: {
+				value: this.textures[ 0 ]
+			}
+		},
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"vUv = vec2( uv.x, uv.y );",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+		fragmentShader: [
+
+			"uniform float mixRatio;",
+
+			"uniform sampler2D tDiffuse1;",
+			"uniform sampler2D tDiffuse2;",
+			"uniform sampler2D tMixTexture;",
+
+			"uniform int useTexture;",
+			"uniform float threshold;",
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"vec4 texel1 = texture2D( tDiffuse1, vUv );",
+			"vec4 texel2 = texture2D( tDiffuse2, vUv );",
+
+			"if (useTexture==1) {",
+
+				"vec4 transitionTexel = texture2D( tMixTexture, vUv );",
+				"float r = mixRatio * (1.0 + threshold * 2.0) - threshold;",
+				"float mixf=clamp((transitionTexel.r - r)*(1.0/threshold), 0.0, 1.0);",
+
+				"gl_FragColor = mix( texel1, texel2, mixf );",
+			"} else {",
+
+				"gl_FragColor = mix( texel2, texel1, mixRatio );",
+
+			"}",
+		"}"
+
+		].join( "\n" )
+
+	} );
+
+	quadgeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
+
+	this.quad = new THREE.Mesh( quadgeometry, this.quadmaterial );
+	this.scene.add( this.quad );
+
+	// Link both scenes and their FBOs
+	this.sceneA = sceneA;
+	this.sceneB = sceneB;
+
+	this.quadmaterial.uniforms.tDiffuse1.value = sceneA.fbo.texture;
+	this.quadmaterial.uniforms.tDiffuse2.value = sceneB.fbo.texture;
+
+	this.needChange = false;
+
+	this.setTextureThreshold = function ( value ) {
+
+		this.quadmaterial.uniforms.threshold.value = value;
+
+	};
+
+	this.useTexture = function ( value ) {
+
+		this.quadmaterial.uniforms.useTexture.value = value ? 1 : 0;
+
+	};
+
+	this.setTexture = function ( i ) {
+
+		this.quadmaterial.uniforms.tMixTexture.value = this.textures[ i ];
+
+	};
+
+	this.render = function( delta ) {
+
+		// Transition animation
+		if ( transitionParams.animateTransition ) {
+
+			var t = ( 1 + Math.sin( transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI ) ) / 2;
+			transitionParams.transition = THREE.Math.smoothstep( t, 0.3, 0.7 );
+
+			// Change the current alpha texture after each transition
+			if ( transitionParams.loopTexture && ( transitionParams.transition == 0 || transitionParams.transition == 1 ) ) {
+
+				if ( this.needChange ) {
+
+					transitionParams.texture = ( transitionParams.texture + 1 ) % this.textures.length;
+					this.quadmaterial.uniforms.tMixTexture.value = this.textures[ transitionParams.texture ];
+					this.needChange = false;
+
+				}
+
+			} else
+				this.needChange = true;
+
+		}
+
+		this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition;
+
+		// Prevent render both scenes when it's not necessary
+		if ( transitionParams.transition == 0 ) {
+
+			this.sceneB.render( delta, false );
+
+		} else if ( transitionParams.transition == 1 ) {
+
+			this.sceneA.render( delta, false );
+
+		} else {
+
+			// When 0<transition<1 render transition between two scenes
+
+			this.sceneA.render( delta, true );
+			this.sceneB.render( delta, true );
+			renderer.render( this.scene, this.cameraOrtho, null, true );
+
+		}
+
+	}
+
+}

+ 65 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSCurve.js

@@ -0,0 +1,65 @@
+/**
+ * @author renej
+ * NURBS curve object
+ *
+ * Derives from Curve, overriding getPoint and getTangent.
+ *
+ * Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
+ *
+ **/
+
+
+/**************************************************************
+ *	NURBS curve
+ **************************************************************/
+
+THREE.NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */ ) {
+
+	this.degree = degree;
+	this.knots = knots;
+	this.controlPoints = [];
+	for ( var i = 0; i < controlPoints.length; ++ i ) {
+
+		// ensure Vector4 for control points
+		var point = controlPoints[ i ];
+		this.controlPoints[ i ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
+
+	}
+
+};
+
+
+THREE.NURBSCurve.prototype = Object.create( THREE.Curve.prototype );
+THREE.NURBSCurve.prototype.constructor = THREE.NURBSCurve;
+
+
+THREE.NURBSCurve.prototype.getPoint = function ( t ) {
+
+	var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] ); // linear mapping t->u
+
+	// following results in (wx, wy, wz, w) homogeneous point
+	var hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u );
+
+	if ( hpoint.w != 1.0 ) {
+
+		// project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
+		hpoint.divideScalar( hpoint.w );
+
+	}
+
+	return new THREE.Vector3( hpoint.x, hpoint.y, hpoint.z );
+
+};
+
+
+THREE.NURBSCurve.prototype.getTangent = function ( t ) {
+
+	var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] );
+	var ders = THREE.NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 );
+	var tangent = ders[ 1 ].clone();
+	tangent.normalize();
+
+	return tangent;
+
+};
+

+ 55 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSSurface.js

@@ -0,0 +1,55 @@
+/**
+ * @author renej
+ * NURBS surface object
+ *
+ * Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
+ *
+ **/
+
+
+/**************************************************************
+ *	NURBS surface
+ **************************************************************/
+
+THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) {
+
+	this.degree1 = degree1;
+	this.degree2 = degree2;
+	this.knots1 = knots1;
+	this.knots2 = knots2;
+	this.controlPoints = [];
+
+	var len1 = knots1.length - degree1 - 1;
+	var len2 = knots2.length - degree2 - 1;
+
+	// ensure Vector4 for control points
+	for ( var i = 0; i < len1; ++ i ) {
+
+		this.controlPoints[ i ] = [];
+		for ( var j = 0; j < len2; ++ j ) {
+
+			var point = controlPoints[ i ][ j ];
+			this.controlPoints[ i ][ j ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
+
+		}
+
+	}
+
+};
+
+
+THREE.NURBSSurface.prototype = {
+
+	constructor: THREE.NURBSSurface,
+
+	getPoint: function ( t1, t2 ) {
+
+		var u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u
+		var v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u
+
+		return THREE.NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v );
+
+	}
+};
+
+

+ 472 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/curves/NURBSUtils.js

@@ -0,0 +1,472 @@
+/**
+ * @author renej
+ * NURBS utils
+ *
+ * See NURBSCurve and NURBSSurface.
+ *
+ **/
+
+
+/**************************************************************
+ *	NURBS Utils
+ **************************************************************/
+
+THREE.NURBSUtils = {
+
+	/*
+	Finds knot vector span.
+
+	p : degree
+	u : parametric value
+	U : knot vector
+	
+	returns the span
+	*/
+	findSpan: function( p,  u,  U ) {
+
+		var n = U.length - p - 1;
+
+		if ( u >= U[ n ] ) {
+
+			return n - 1;
+
+		}
+
+		if ( u <= U[ p ] ) {
+
+			return p;
+
+		}
+
+		var low = p;
+		var high = n;
+		var mid = Math.floor( ( low + high ) / 2 );
+
+		while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
+		  
+			if ( u < U[ mid ] ) {
+
+				high = mid;
+
+			} else {
+
+				low = mid;
+
+			}
+
+			mid = Math.floor( ( low + high ) / 2 );
+
+		}
+
+		return mid;
+
+	},
+    
+		
+	/*
+	Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
+   
+	span : span in which u lies
+	u    : parametric point
+	p    : degree
+	U    : knot vector
+	
+	returns array[p+1] with basis functions values.
+	*/
+	calcBasisFunctions: function( span, u, p, U ) {
+
+		var N = [];
+		var left = [];
+		var right = [];
+		N[ 0 ] = 1.0;
+
+		for ( var j = 1; j <= p; ++ j ) {
+	   
+			left[ j ] = u - U[ span + 1 - j ];
+			right[ j ] = U[ span + j ] - u;
+
+			var saved = 0.0;
+
+			for ( var r = 0; r < j; ++ r ) {
+
+				var rv = right[ r + 1 ];
+				var lv = left[ j - r ];
+				var temp = N[ r ] / ( rv + lv );
+				N[ r ] = saved + rv * temp;
+				saved = lv * temp;
+
+			 }
+
+			 N[ j ] = saved;
+
+		 }
+
+		 return N;
+
+	},
+
+
+	/*
+	Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
+ 
+	p : degree of B-Spline
+	U : knot vector
+	P : control points (x, y, z, w)
+	u : parametric point
+
+	returns point for given u
+	*/
+	calcBSplinePoint: function( p, U, P, u ) {
+
+		var span = this.findSpan( p, u, U );
+		var N = this.calcBasisFunctions( span, u, p, U );
+		var C = new THREE.Vector4( 0, 0, 0, 0 );
+
+		for ( var j = 0; j <= p; ++ j ) {
+
+			var point = P[ span - p + j ];
+			var Nj = N[ j ];
+			var wNj = point.w * Nj;
+			C.x += point.x * wNj;
+			C.y += point.y * wNj;
+			C.z += point.z * wNj;
+			C.w += point.w * Nj;
+
+		}
+
+		return C;
+
+	},
+
+
+	/*
+	Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
+
+	span : span in which u lies
+	u    : parametric point
+	p    : degree
+	n    : number of derivatives to calculate
+	U    : knot vector
+
+	returns array[n+1][p+1] with basis functions derivatives
+	*/
+	calcBasisFunctionDerivatives: function( span,  u,  p,  n,  U ) {
+
+		var zeroArr = [];
+		for ( var i = 0; i <= p; ++ i )
+			zeroArr[ i ] = 0.0;
+
+		var ders = [];
+		for ( var i = 0; i <= n; ++ i )
+			ders[ i ] = zeroArr.slice( 0 );
+
+		var ndu = [];
+		for ( var i = 0; i <= p; ++ i )
+			ndu[ i ] = zeroArr.slice( 0 );
+
+		ndu[ 0 ][ 0 ] = 1.0;
+
+		var left = zeroArr.slice( 0 );
+		var right = zeroArr.slice( 0 );
+
+		for ( var j = 1; j <= p; ++ j ) {
+
+			left[ j ] = u - U[ span + 1 - j ];
+			right[ j ] = U[ span + j ] - u;
+
+			var saved = 0.0;
+
+			for ( var r = 0; r < j; ++ r ) {
+
+				var rv = right[ r + 1 ];
+				var lv = left[ j - r ];
+				ndu[ j ][ r ] = rv + lv;
+
+				var temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
+				ndu[ r ][ j ] = saved + rv * temp;
+				saved = lv * temp;
+
+			}
+
+			ndu[ j ][ j ] = saved;
+
+		}
+
+		for ( var j = 0; j <= p; ++ j ) {
+
+			ders[ 0 ][ j ] = ndu[ j ][ p ];
+
+		}
+
+		for ( var r = 0; r <= p; ++ r ) {
+
+			var s1 = 0;
+			var s2 = 1;
+
+			var a = [];
+			for ( var i = 0; i <= p; ++ i ) {
+
+				a[ i ] = zeroArr.slice( 0 );
+
+			}
+			a[ 0 ][ 0 ] = 1.0;
+
+			for ( var k = 1; k <= n; ++ k ) {
+
+				var d = 0.0;
+				var rk = r - k;
+				var pk = p - k;
+
+				if ( r >= k ) {
+
+					a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
+					d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
+
+				}
+
+				var j1 = ( rk >= - 1 ) ? 1 : - rk;
+				var j2 = ( r - 1 <= pk ) ? k - 1 :  p - r;
+
+				for ( var j = j1; j <= j2; ++ j ) {
+
+					a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
+					d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
+
+				}
+
+				if ( r <= pk ) {
+
+					a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
+					d += a[ s2 ][ k ] * ndu[ r ][ pk ];
+
+				}
+
+				ders[ k ][ r ] = d;
+
+				var j = s1;
+				s1 = s2;
+				s2 = j;
+
+			}
+
+		}
+
+		var r = p;
+
+		for ( var k = 1; k <= n; ++ k ) {
+
+			for ( var j = 0; j <= p; ++ j ) {
+
+				ders[ k ][ j ] *= r;
+
+			}
+			r *= p - k;
+
+		}
+
+		return ders;
+
+	},
+
+
+	/*
+		Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
+
+		p  : degree
+		U  : knot vector
+		P  : control points
+		u  : Parametric points
+		nd : number of derivatives
+
+		returns array[d+1] with derivatives
+		*/
+	calcBSplineDerivatives: function( p,  U,  P,  u,  nd ) {
+
+		var du = nd < p ? nd : p;
+		var CK = [];
+		var span = this.findSpan( p, u, U );
+		var nders = this.calcBasisFunctionDerivatives( span, u, p, du, U );
+		var Pw = [];
+
+		for ( var i = 0; i < P.length; ++ i ) {
+
+			var point = P[ i ].clone();
+			var w = point.w;
+
+			point.x *= w;
+			point.y *= w;
+			point.z *= w;
+
+			Pw[ i ] = point;
+
+		}
+		for ( var k = 0; k <= du; ++ k ) {
+
+			var point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
+
+			for ( var j = 1; j <= p; ++ j ) {
+
+				point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
+
+			}
+
+			CK[ k ] = point;
+
+		}
+
+		for ( var k = du + 1; k <= nd + 1; ++ k ) {
+
+			CK[ k ] = new THREE.Vector4( 0, 0, 0 );
+
+		}
+
+		return CK;
+
+	},
+
+
+	/*
+	Calculate "K over I"
+
+	returns k!/(i!(k-i)!)
+	*/
+	calcKoverI: function( k, i ) {
+
+		var nom = 1;
+
+		for ( var j = 2; j <= k; ++ j ) {
+
+			nom *= j;
+
+		}
+
+		var denom = 1;
+
+		for ( var j = 2; j <= i; ++ j ) {
+
+			denom *= j;
+
+		}
+
+		for ( var j = 2; j <= k - i; ++ j ) {
+
+			denom *= j;
+
+		}
+
+		return nom / denom;
+
+	},
+
+
+	/*
+	Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
+
+	Pders : result of function calcBSplineDerivatives
+
+	returns array with derivatives for rational curve.
+	*/
+	calcRationalCurveDerivatives: function ( Pders ) {
+
+		var nd = Pders.length;
+		var Aders = [];
+		var wders = [];
+
+		for ( var i = 0; i < nd; ++ i ) {
+
+			var point = Pders[ i ];
+			Aders[ i ] = new THREE.Vector3( point.x, point.y, point.z );
+			wders[ i ] = point.w;
+
+		}
+
+		var CK = [];
+
+		for ( var k = 0; k < nd; ++ k ) {
+
+			var v = Aders[ k ].clone();
+
+			for ( var i = 1; i <= k; ++ i ) {
+
+				v.sub( CK[ k - i ].clone().multiplyScalar( this.calcKoverI( k, i ) * wders[ i ] ) );
+
+			}
+
+			CK[ k ] = v.divideScalar( wders[ 0 ] );
+
+		}
+
+		return CK;
+
+	},
+
+
+	/*
+	Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
+
+	p  : degree
+	U  : knot vector
+	P  : control points in homogeneous space
+	u  : parametric points
+	nd : number of derivatives
+
+	returns array with derivatives.
+	*/
+	calcNURBSDerivatives: function( p,  U,  P,  u,  nd ) {
+
+		var Pders = this.calcBSplineDerivatives( p, U, P, u, nd );
+		return this.calcRationalCurveDerivatives( Pders );
+
+	},
+
+
+	/*
+	Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
+ 
+	p1, p2 : degrees of B-Spline surface
+	U1, U2 : knot vectors
+	P      : control points (x, y, z, w)
+	u, v   : parametric values
+
+	returns point for given (u, v)
+	*/
+	calcSurfacePoint: function( p, q, U, V, P, u, v ) {
+
+		var uspan = this.findSpan( p, u, U );
+		var vspan = this.findSpan( q, v, V );
+		var Nu = this.calcBasisFunctions( uspan, u, p, U );
+		var Nv = this.calcBasisFunctions( vspan, v, q, V );
+		var temp = [];
+
+		for ( var l = 0; l <= q; ++ l ) {
+
+			temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 );
+			for ( var k = 0; k <= p; ++ k ) {
+
+				var point = P[ uspan - p + k ][ vspan - q + l ].clone();
+				var w = point.w;
+				point.x *= w;
+				point.y *= w;
+				point.z *= w;
+				temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
+
+			}
+
+		}
+
+		var Sw = new THREE.Vector4( 0, 0, 0, 0 );
+		for ( var l = 0; l <= q; ++ l ) {
+
+			Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
+
+		}
+
+		Sw.divideScalar( Sw.w );
+		return new THREE.Vector3( Sw.x, Sw.y, Sw.z );
+
+	}
+
+};
+
+
+

+ 152 - 0
node_modules/three-orbitcontrols-ts/node_modules/three/examples/js/effects/AnaglyphEffect.js

@@ -0,0 +1,152 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author marklundin / http://mark-lundin.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author tschw
+ */
+
+THREE.AnaglyphEffect = function ( renderer, width, height ) {
+
+	// Matrices generated with angler.js https://github.com/tschw/angler.js/
+	// (in column-major element order, as accepted by WebGL)
+
+	this.colorMatrixLeft = new THREE.Matrix3().fromArray( [
+
+			1.0671679973602295, 	-0.0016435992438346148,		 0.0001777536963345483, // r out
+			-0.028107794001698494,	-0.00019593400065787137,	-0.0002875397040043026, // g out
+			-0.04279090091586113,	 0.000015809757314855233,	-0.00024287120322696865 // b out
+
+	] );
+
+	//		red						green 						blue  						in
+
+	this.colorMatrixRight = new THREE.Matrix3().fromArray( [
+
+			-0.0355340838432312,	-0.06440307199954987,		 0.018319187685847282,	// r out
+			-0.10269022732973099,	 0.8079727292060852,		-0.04835830628871918,	// g out
+			0.0001224992738571018,	-0.009558862075209618,		 0.567823588848114		// b out
+
+	] );
+
+	var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
+
+	var _scene = new THREE.Scene();
+
+	var _stereo = new THREE.StereoCamera();
+
+	var _params = { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat };
+
+	if ( width === undefined ) width = 512;
+	if ( height === undefined ) height = 512;
+
+	var _renderTargetL = new THREE.WebGLRenderTarget( width, height, _params );
+	var _renderTargetR = new THREE.WebGLRenderTarget( width, height, _params );
+
+	var _material = new THREE.ShaderMaterial( {
+
+		uniforms: {
+
+			"mapLeft": { value: _renderTargetL.texture },
+			"mapRight": { value: _renderTargetR.texture },
+
+			"colorMatrixLeft": { value: this.colorMatrixLeft },
+			"colorMatrixRight": { value: this.colorMatrixRight }
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"	vUv = vec2( uv.x, uv.y );",
+			"	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform sampler2D mapLeft;",
+			"uniform sampler2D mapRight;",
+			"varying vec2 vUv;",
+
+			"uniform mat3 colorMatrixLeft;",
+			"uniform mat3 colorMatrixRight;",
+
+			// These functions implement sRGB linearization and gamma correction
+
+			"float lin( float c ) {",
+			"	return c <= 0.04045 ? c * 0.0773993808 :",
+			"			pow( c * 0.9478672986 + 0.0521327014, 2.4 );",
+			"}",
+
+			"vec4 lin( vec4 c ) {",
+			"	return vec4( lin( c.r ), lin( c.g ), lin( c.b ), c.a );",
+			"}",
+
+			"float dev( float c ) {",
+			"	return c <= 0.0031308 ? c * 12.92",
+			"			: pow( c, 0.41666 ) * 1.055 - 0.055;",
+			"}",
+
+
+			"void main() {",
+
+			"	vec2 uv = vUv;",
+
+			"	vec4 colorL = lin( texture2D( mapLeft, uv ) );",
+			"	vec4 colorR = lin( texture2D( mapRight, uv ) );",
+
+			"	vec3 color = clamp(",
+			"			colorMatrixLeft * colorL.rgb +",
+			"			colorMatrixRight * colorR.rgb, 0., 1. );",
+
+			"	gl_FragColor = vec4(",
+			"			dev( color.r ), dev( color.g ), dev( color.b ),",
+			"			max( colorL.a, colorR.a ) );",
+
+			"}"
+
+		].join( "\n" )
+
+	} );
+
+	var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), _material );
+	_scene.add( mesh );
+
+	this.setSize = function ( width, height ) {
+
+		renderer.setSize( width, height );
+
+		var pixelRatio = renderer.getPixelRatio();
+
+		_renderTargetL.setSize( width * pixelRatio, height * pixelRatio );
+		_renderTargetR.setSize( width * pixelRatio, height * pixelRatio );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		_stereo.update( camera );
+
+		renderer.render( scene, _stereo.cameraL, _renderTargetL, true );
+		renderer.render( scene, _stereo.cameraR, _renderTargetR, true );
+		renderer.render( _scene, _camera );
+
+	};
+
+	this.dispose = function() {
+
+		if ( _renderTargetL ) _renderTargetL.dispose();
+		if ( _renderTargetR ) _renderTargetR.dispose();
+
+	};
+
+};

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels