OrbitControls = function OrbitControls(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 _three2['default'].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: _three2['default'].MOUSE.LEFT, ZOOM: _three2['default'].MOUSE.MIDDLE, PAN: _three2['default'].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 phi;
		};
	
		this.getAzimuthalAngle = function () {
	
			return 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 _three2['default'].Vector3();
	
			// so camera.up is the orbit axis
			var quat = new _three2['default'].Quaternion().setFromUnitVectors(object.up, new _three2['default'].Vector3(0, 1, 0));
			var quatInverse = quat.clone().inverse();
	
			var lastPosition = new _three2['default'].Vector3();
			var lastQuaternion = new _three2['default'].Quaternion();
	
			return function () {
	
				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
	
				theta = Math.atan2(offset.x, offset.z);
	
				// angle from y-axis
	
				phi = Math.atan2(Math.sqrt(offset.x * offset.x + offset.z * offset.z), offset.y);
	
				if (scope.autoRotate && state === STATE.NONE) {
	
					rotateLeft(getAutoRotationAngle());
				}
	
				theta += thetaDelta;
				phi += phiDelta;
	
				// restrict theta to be between desired limits
				theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, theta));
	
				// restrict phi to be between desired limits
				phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, phi));
	
				// restrict phi to be betwee EPS and PI-EPS
				phi = Math.max(EPS, Math.min(Math.PI - EPS, phi));
	
				var radius = offset.length() * scale;
	
				// restrict radius to be between desired limits
				radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, radius));
	
				// move target to panned location
				scope.target.add(panOffset);
	
				offset.x = radius * Math.sin(phi) * Math.sin(theta);
				offset.y = radius * Math.cos(phi);
				offset.z = radius * Math.sin(phi) * Math.cos(theta);
	
				// 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) {
	
					thetaDelta *= 1 - scope.dampingFactor;
					phiDelta *= 1 - scope.dampingFactor;
				} else {
	
					thetaDelta = 0;
					phiDelta = 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('mousewheel', onMouseWheel, false);
			scope.domElement.removeEventListener('MozMousePixelScroll', onMouseWheel, false); // firefox
	
			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);
			document.removeEventListener('mouseout', 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 theta;
		var phi;
	
		var phiDelta = 0;
		var thetaDelta = 0;
		var scale = 1;
		var panOffset = new _three2['default'].Vector3();
		var zoomChanged = false;
	
		var rotateStart = new _three2['default'].Vector2();
		var rotateEnd = new _three2['default'].Vector2();
		var rotateDelta = new _three2['default'].Vector2();
	
		var panStart = new _three2['default'].Vector2();
		var panEnd = new _three2['default'].Vector2();
		var panDelta = new _three2['default'].Vector2();
	
		var dollyStart = new _three2['default'].Vector2();
		var dollyEnd = new _three2['default'].Vector2();
		var dollyDelta = new _three2['default'].Vector2();
	
		function getAutoRotationAngle() {
	
			return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
		}
	
		function getZoomScale() {
	
			return Math.pow(0.95, scope.zoomSpeed);
		}
	
		function rotateLeft(angle) {
	
			thetaDelta -= angle;
		}
	
		function rotateUp(angle) {
	
			phiDelta -= angle;
		}
	
		var panLeft = (function () {
	
			var v = new _three2['default'].Vector3();
	
			// return function panLeft( distance, objectMatrix ) {
			//
			// 	var te = objectMatrix.elements;
			//
			// 	// get X column of objectMatrix
			// 	v.set( te[ 0 ], te[ 1 ], te[ 2 ] );
			//
			// 	v.multiplyScalar( - distance );
			//
			// 	panOffset.add( v );
			//
			// };
	
			// Fixed panning to x/y plane
			return function panLeft(distance, objectMatrix) {
				var te = objectMatrix.elements;
				// var adjDist = distance / Math.cos(phi);
	
				v.set(te[0], 0, te[2]);
				v.multiplyScalar(-distance);
	
				panOffset.add(v);
			};
		})();
	
		// Fixed panning to x/y plane
		var panUp = (function () {
	
			var v = new _three2['default'].Vector3();
	
			// return function panUp( distance, objectMatrix ) {
			//
			// 	var te = objectMatrix.elements;
			//
			// 	// get Y column of objectMatrix
			// 	v.set( te[ 4 ], te[ 5 ], te[ 6 ] );
			//
			// 	v.multiplyScalar( distance );
			//
			// 	panOffset.add( v );
			//
			// };
	
			return function panUp(distance, objectMatrix) {
				var te = objectMatrix.elements;
				var adjDist = distance / Math.cos(phi);
	
				v.set(te[4], 0, te[6]);
				v.multiplyScalar(adjDist);
	
				panOffset.add(v);
			};
		})();
	
		// deltaX and deltaY are in pixels; right and down are positive
		var pan = (function () {
	
			var offset = new _three2['default'].Vector3();
	
			return function (deltaX, deltaY) {
	
				var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
	
				if (scope.object instanceof _three2['default'].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 _three2['default'].OrthographicCamera) {
	
					// orthographic
					panLeft(deltaX * (scope.object.right - scope.object.left) / element.clientWidth, scope.object.matrix);
					panUp(deltaY * (scope.object.top - scope.object.bottom) / 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 _three2['default'].PerspectiveCamera) {
	
				scale /= dollyScale;
			} else if (scope.object instanceof _three2['default'].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 _three2['default'].PerspectiveCamera) {
	
				scale *= dollyScale;
			} else if (scope.object instanceof _three2['default'].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' );
	
			var delta = 0;
	
			if (event.wheelDelta !== undefined) {
	
				// WebKit / Opera / Explorer 9
	
				delta = event.wheelDelta;
			} else if (event.detail !== undefined) {
	
				// Firefox
	
				delta = -event.detail;
			}
	
			if (delta > 0) {
	
				dollyOut(getZoomScale());
			} else if (delta < 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.pointers[0].pageX, event.pointers[0].pageY);
		}
	
		function handleTouchStartDolly(event) {
	
			//console.log( 'handleTouchStartDolly' );
	
			var dx = event.pointers[0].pageX - event.pointers[1].pageX;
			var dy = event.pointers[0].pageY - event.pointers[1].pageY;
	
			var distance = Math.sqrt(dx * dx + dy * dy);
	
			dollyStart.set(0, distance);
		}
	
		function handleTouchStartPan(event) {
	
			//console.log( 'handleTouchStartPan' );
	
			panStart.set(event.deltaX, event.deltaY);
		}
	
		function handleTouchMoveRotate(event) {
	
			//console.log( 'handleTouchMoveRotate' );
	
			rotateEnd.set(event.pointers[0].pageX, event.pointers[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.pointers[0].pageX - event.pointers[1].pageX;
			var dy = event.pointers[0].pageY - event.pointers[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.deltaX, event.deltaY);
	
			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);
				document.addEventListener('mouseout', 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);
			document.removeEventListener('mouseout', onMouseUp, false);
	
			scope.dispatchEvent(endEvent);
	
			state = STATE.NONE;
		}
	
		function onMouseWheel(event) {
	
			if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) 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('mousewheel', onMouseWheel, false);
		scope.domElement.addEventListener('MozMousePixelScroll', onMouseWheel, false); // firefox
	
		// scope.domElement.addEventListener( 'touchstart', onTouchStart, false );
		// scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
		// scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
	
		scope.hammer = new _hammerjs2['default'](scope.domElement);
	
		scope.hammer.get('pan').set({
			pointers: 0,
			direction: _hammerjs2['default'].DIRECTION_ALL
		});
	
		scope.hammer.get('pinch').set({
			enable: true,
			threshold: 0.1
		});
	
		scope.hammer.on('panstart', function (event) {
			if (scope.enabled === false) {
				return;
			}
	
			if (event.pointerType === 'mouse') {
				return;
			}
	
			if (event.pointers.length === 1) {
				if (scope.enablePan === false) {
					return;
				}
	
				handleTouchStartPan(event);
				// panStart.set(event.deltaX, event.deltaY);
	
				state = STATE.TOUCH_PAN;
			} else if (event.pointers.length === 2) {
				if (scope.enableRotate === false) return;
	
				handleTouchStartRotate(event);
	
				state = STATE.TOUCH_ROTATE;
			}
	
			if (state !== STATE.NONE) {
				scope.dispatchEvent(startEvent);
			}
		});
	
		scope.hammer.on('panend', function (event) {
			if (event.pointerType === 'mouse') {
				return;
			}
	
			onTouchEnd(event);
		});
	
		scope.hammer.on('panmove', function (event) {
			if (scope.enabled === false) return;
	
			if (event.pointerType === 'mouse') {
				return;
			}
	
			// event.preventDefault();
			// event.stopPropagation();
	
			if (event.pointers.length === 1) {
				if (scope.enablePan === false) return;
				if (state !== STATE.TOUCH_PAN) return; // is this needed?...
	
				handleTouchMovePan(event);
	
				// panEnd.set( event.deltaX, event.deltaY );
				//
				// panDelta.subVectors( panEnd, panStart );
				//
				// pan( panDelta.x, panDelta.y );
				//
				// panStart.copy( panEnd );
				//
				// scope.update();
			} else if (event.pointers.length === 2) {
					if (scope.enableRotate === false) return;
					if (state !== STATE.TOUCH_ROTATE) return; // is this needed?...
	
					handleTouchMoveRotate(event);
				}
		});
	
		scope.hammer.on('pinchstart', function (event) {
			if (scope.enabled === false) return;
	
			if (event.pointerType === 'mouse') {
				return;
			}
	
			if (scope.enableZoom === false) return;
	
			handleTouchStartDolly(event);
	
			// var dx = event.pointers[ 0 ].pageX - event.pointers[ 1 ].pageX;
			// var dy = event.pointers[ 0 ].pageY - event.pointers[ 1 ].pageY;
			//
			// var distance = Math.sqrt( dx * dx + dy * dy );
			//
			// dollyStart.set( 0, distance );
			//
			state = STATE.TOUCH_DOLLY;
	
			if (state !== STATE.NONE) {
				scope.dispatchEvent(startEvent);
			}
		});
	
		scope.hammer.on('pinchend', function (event) {
			if (event.pointerType === 'mouse') {
				return;
			}
	
			onTouchEnd(event);
		});
	
		scope.hammer.on('pinchmove', function (event) {
			if (scope.enabled === false) return;
	
			if (event.pointerType === 'mouse') {
				return;
			}
	
			// event.preventDefault();
			// event.stopPropagation();
	
			if (scope.enableZoom === false) return;
			if (state !== STATE.TOUCH_DOLLY) return; // is this needed?...
	
			handleTouchMoveDolly(event);
	
			// var dx = event.pointers[ 0 ].pageX - event.pointers[ 1 ].pageX;
			// var dy = event.pointers[ 0 ].pageY - event.pointers[ 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();
		});
	
		window.addEventListener('keydown', onKeyDown, false);
	
		// Expose controls methods for programmatic control
		this.panLeft = panLeft;
		this.panUp = panUp;
		this.pan = pan;
		this.dollyIn = dollyIn;
		this.dollyOut = dollyOut;
		this.getZoomScale = getZoomScale;
		this.rotateLeft = rotateLeft;
		this.rotateUp = rotateUp;
	
		// force an update at start
	
		this.update();
	}
@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