Spaces:
Running
Running
| // 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 left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move | |
| // Simplified and fixed version for GXS - QuantumNexus | |
| 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, the interval [min, max] must be a sub-interval of [- 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.05; | |
| // 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.panSpeed = 1.0; | |
| this.screenSpacePanning = true; // if false, pan orthogonal to world-space direction camera.up | |
| 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 orbit 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 = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN }; | |
| // Touch fingers | |
| this.touches = { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN }; | |
| // for reset | |
| this.target0 = this.target.clone(); | |
| this.position0 = this.object.position.clone(); | |
| this.zoom0 = this.object.zoom; | |
| // State variables | |
| this.changeEvent = { type: 'change' }; | |
| this.startEvent = { type: 'start' }; | |
| this.endEvent = { type: 'end' }; | |
| this.STATE = { | |
| NONE: - 1, | |
| ROTATE: 0, | |
| DOLLY: 1, | |
| PAN: 2, | |
| TOUCH_ROTATE: 3, | |
| TOUCH_PAN: 4, | |
| TOUCH_DOLLY_PAN: 5, | |
| TOUCH_DOLLY_ROTATE: 6 | |
| }; | |
| var state = this.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(); | |
| var scope = this; | |
| 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) { | |
| if (scope.screenSpacePanning === true) { | |
| v.setFromMatrixColumn(objectMatrix, 1); | |
| } else { | |
| v.setFromMatrixColumn(objectMatrix, 0); | |
| v.crossVectors(scope.object.up, v); | |
| } | |
| v.multiplyScalar(distance); | |
| panOffset.add(v); | |
| }; | |
| }(); | |
| function dollyOut(dollyScale) { | |
| if (scope.object.isPerspectiveCamera) { | |
| scale /= dollyScale; | |
| } else if (scope.object.isOrthographicCamera) { | |
| 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 dollyIn(dollyScale) { | |
| if (scope.object.isPerspectiveCamera) { | |
| scale *= dollyScale; | |
| } else if (scope.object.isOrthographicCamera) { | |
| 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) { | |
| rotateStart.set(event.clientX, event.clientY); | |
| } | |
| function handleMouseDownDolly(event) { | |
| dollyStart.set(event.clientX, event.clientY); | |
| } | |
| function handleMouseDownPan(event) { | |
| panStart.set(event.clientX, event.clientY); | |
| } | |
| function handleMouseMoveRotate(event) { | |
| rotateEnd.set(event.clientX, event.clientY); | |
| rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); | |
| var element = scope.domElement; | |
| rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); // yes, height | |
| rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); | |
| rotateStart.copy(rotateEnd); | |
| scope.update(); | |
| } | |
| function handleMouseMoveDolly(event) { | |
| 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) { | |
| panEnd.set(event.clientX, event.clientY); | |
| panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); | |
| pan(panDelta.x, panDelta.y); | |
| panStart.copy(panEnd); | |
| scope.update(); | |
| } | |
| function handleMouseWheel(event) { | |
| if (event.deltaY < 0) { | |
| dollyOut(getZoomScale()); | |
| } else if (event.deltaY > 0) { | |
| dollyIn(getZoomScale()); | |
| } | |
| scope.update(); | |
| } | |
| function handleKeyDown(event) { | |
| var needsUpdate = false; | |
| switch (event.keyCode) { | |
| case scope.keys.UP: | |
| pan(0, scope.keyPanSpeed); | |
| needsUpdate = true; | |
| break; | |
| case scope.keys.BOTTOM: | |
| pan(0, - scope.keyPanSpeed); | |
| needsUpdate = true; | |
| break; | |
| case scope.keys.LEFT: | |
| pan(scope.keyPanSpeed, 0); | |
| needsUpdate = true; | |
| break; | |
| case scope.keys.RIGHT: | |
| pan(- scope.keyPanSpeed, 0); | |
| needsUpdate = true; | |
| break; | |
| } | |
| if (needsUpdate) { | |
| event.preventDefault(); | |
| scope.update(); | |
| } | |
| } | |
| function handleTouchStartRotate(event) { | |
| if (event.touches.length === 1) { | |
| rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); | |
| } else { | |
| var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); | |
| var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); | |
| rotateStart.set(x, y); | |
| } | |
| } | |
| function handleTouchStartPan(event) { | |
| if (event.touches.length === 1) { | |
| panStart.set(event.touches[0].pageX, event.touches[0].pageY); | |
| } else { | |
| var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); | |
| var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); | |
| panStart.set(x, y); | |
| } | |
| } | |
| function handleTouchStartDolly(event) { | |
| 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 handleTouchStartDollyPan(event) { | |
| if (scope.enableZoom) handleTouchStartDolly(event); | |
| if (scope.enablePan) handleTouchStartPan(event); | |
| } | |
| function handleTouchStartDollyRotate(event) { | |
| if (scope.enableZoom) handleTouchStartDolly(event); | |
| if (scope.enableRotate) handleTouchStartRotate(event); | |
| } | |
| function handleTouchMoveRotate(event) { | |
| if (event.touches.length === 1) { | |
| rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); | |
| } else { | |
| var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); | |
| var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); | |
| rotateEnd.set(x, y); | |
| } | |
| rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed); | |
| var element = scope.domElement; | |
| rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight); // yes, height | |
| rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight); | |
| rotateStart.copy(rotateEnd); | |
| } | |
| function handleTouchMovePan(event) { | |
| if (event.touches.length === 1) { | |
| panEnd.set(event.touches[0].pageX, event.touches[0].pageY); | |
| } else { | |
| var x = 0.5 * (event.touches[0].pageX + event.touches[1].pageX); | |
| var y = 0.5 * (event.touches[0].pageY + event.touches[1].pageY); | |
| panEnd.set(x, y); | |
| } | |
| panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed); | |
| pan(panDelta.x, panDelta.y); | |
| panStart.copy(panEnd); | |
| } | |
| function handleTouchMoveDolly(event) { | |
| 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.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed)); | |
| dollyOut(dollyDelta.y); | |
| dollyStart.copy(dollyEnd); | |
| } | |
| function handleTouchMoveDollyPan(event) { | |
| if (scope.enableZoom) handleTouchMoveDolly(event); | |
| if (scope.enablePan) handleTouchMovePan(event); | |
| } | |
| function handleTouchMoveDollyRotate(event) { | |
| if (scope.enableZoom) handleTouchMoveDolly(event); | |
| if (scope.enableRotate) handleTouchMoveRotate(event); | |
| } | |
| // event handlers - FSM: listen for events and reset state | |
| function onMouseDown(event) { | |
| if (scope.enabled === false) return; | |
| event.preventDefault(); | |
| switch (event.button) { | |
| case 0: | |
| if (scope.enableRotate === false) return; | |
| handleMouseDownRotate(event); | |
| state = scope.STATE.ROTATE; | |
| break; | |
| case 1: | |
| if (scope.enableZoom === false) return; | |
| handleMouseDownDolly(event); | |
| state = scope.STATE.DOLLY; | |
| break; | |
| case 2: | |
| if (scope.enablePan === false) return; | |
| handleMouseDownPan(event); | |
| state = scope.STATE.PAN; | |
| break; | |
| } | |
| if (state !== scope.STATE.NONE) { | |
| document.addEventListener('mousemove', onMouseMove, false); | |
| document.addEventListener('mouseup', onMouseUp, false); | |
| scope.dispatchEvent(scope.startEvent); | |
| } | |
| } | |
| function onMouseMove(event) { | |
| if (scope.enabled === false) return; | |
| event.preventDefault(); | |
| switch (state) { | |
| case scope.STATE.ROTATE: | |
| if (scope.enableRotate === false) return; | |
| handleMouseMoveRotate(event); | |
| break; | |
| case scope.STATE.DOLLY: | |
| if (scope.enableZoom === false) return; | |
| handleMouseMoveDolly(event); | |
| break; | |
| case scope.STATE.PAN: | |
| if (scope.enablePan === false) return; | |
| handleMouseMovePan(event); | |
| break; | |
| } | |
| } | |
| function onMouseUp(event) { | |
| if (scope.enabled === false) return; | |
| document.removeEventListener('mousemove', onMouseMove, false); | |
| document.removeEventListener('mouseup', onMouseUp, false); | |
| scope.dispatchEvent(scope.endEvent); | |
| state = scope.STATE.NONE; | |
| } | |
| function onMouseWheel(event) { | |
| if (scope.enabled === false || scope.enableZoom === false || state !== scope.STATE.NONE) return; | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| scope.dispatchEvent(scope.startEvent); | |
| handleMouseWheel(event); | |
| scope.dispatchEvent(scope.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; | |
| event.preventDefault(); | |
| switch (event.touches.length) { | |
| case 1: | |
| switch (scope.touches.ONE) { | |
| case THREE.TOUCH.ROTATE: | |
| if (scope.enableRotate === false) return; | |
| handleTouchStartRotate(event); | |
| state = scope.STATE.TOUCH_ROTATE; | |
| break; | |
| case THREE.TOUCH.PAN: | |
| if (scope.enablePan === false) return; | |
| handleTouchStartPan(event); | |
| state = scope.STATE.TOUCH_PAN; | |
| break; | |
| default: | |
| state = scope.STATE.NONE; | |
| } | |
| break; | |
| case 2: | |
| switch (scope.touches.TWO) { | |
| case THREE.TOUCH.DOLLY_PAN: | |
| if (scope.enableZoom === false && scope.enablePan === false) return; | |
| handleTouchStartDollyPan(event); | |
| state = scope.STATE.TOUCH_DOLLY_PAN; | |
| break; | |
| case THREE.TOUCH.DOLLY_ROTATE: | |
| if (scope.enableZoom === false && scope.enableRotate === false) return; | |
| handleTouchStartDollyRotate(event); | |
| state = scope.STATE.TOUCH_DOLLY_ROTATE; | |
| break; | |
| default: | |
| state = scope.STATE.NONE; | |
| } | |
| break; | |
| default: | |
| state = scope.STATE.NONE; | |
| } | |
| if (state !== scope.STATE.NONE) { | |
| scope.dispatchEvent(scope.startEvent); | |
| } | |
| } | |
| function onTouchMove(event) { | |
| if (scope.enabled === false) return; | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| switch (state) { | |
| case scope.STATE.TOUCH_ROTATE: | |
| if (scope.enableRotate === false) return; | |
| handleTouchMoveRotate(event); | |
| scope.update(); | |
| break; | |
| case scope.STATE.TOUCH_PAN: | |
| if (scope.enablePan === false) return; | |
| handleTouchMovePan(event); | |
| scope.update(); | |
| break; | |
| case scope.STATE.TOUCH_DOLLY_PAN: | |
| if (scope.enableZoom === false && scope.enablePan === false) return; | |
| handleTouchMoveDollyPan(event); | |
| scope.update(); | |
| break; | |
| case scope.STATE.TOUCH_DOLLY_ROTATE: | |
| if (scope.enableZoom === false && scope.enableRotate === false) return; | |
| handleTouchMoveDollyRotate(event); | |
| scope.update(); | |
| break; | |
| default: | |
| state = scope.STATE.NONE; | |
| } | |
| } | |
| function onTouchEnd(event) { | |
| if (scope.enabled === false) return; | |
| scope.dispatchEvent(scope.endEvent); | |
| state = scope.STATE.NONE; | |
| } | |
| function onContextMenu(event) { | |
| if (scope.enabled === false) return; | |
| 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 = 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 === scope.STATE.NONE) { | |
| rotateLeft(getAutoRotationAngle()); | |
| } | |
| if (scope.enableDamping) { | |
| spherical.theta += sphericalDelta.theta * scope.dampingFactor; | |
| spherical.phi += sphericalDelta.phi * scope.dampingFactor; | |
| } else { | |
| 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 | |
| if (scope.enableDamping === true) { | |
| scope.target.addScaledVector(panOffset, scope.dampingFactor); | |
| } else { | |
| 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); | |
| panOffset.multiplyScalar(1 - scope.dampingFactor); | |
| } else { | |
| sphericalDelta.set(0, 0, 0); | |
| panOffset.set(0, 0, 0); | |
| } | |
| scale = 1; | |
| // 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(scope.changeEvent); | |
| lastPosition.copy(scope.object.position); | |
| lastQuaternion.copy(scope.object.quaternion); | |
| zoomChanged = false; | |
| return true; | |
| } | |
| return false; | |
| }; | |
| }(); | |
| function pan(deltaX, deltaY) { | |
| var element = scope.domElement === document ? scope.domElement.body : scope.domElement; | |
| if (scope.object.isPerspectiveCamera) { | |
| // perspective | |
| var position = scope.object.position; | |
| var offset = position.clone().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 use only clientHeight here so aspect ratio does not distort speed | |
| panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix); | |
| panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix); | |
| } else if (scope.object.isOrthographicCamera) { | |
| // 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; | |
| } | |
| }; | |
| 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); | |
| }; | |
| }; | |
| THREE.OrbitControls.prototype = Object.create(THREE.EventDispatcher.prototype); | |
| THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; | |
| // This ensures backward compatibility with older THREE.js versions | |
| if (typeof THREE.MOUSE === 'undefined') { | |
| THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; | |
| } | |
| if (typeof THREE.TOUCH === 'undefined') { | |
| THREE.TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; | |
| } |