From 51346f788b21479f534fdcde25fb481edcf3a2b1 Mon Sep 17 00:00:00 2001 From: Xueqiao Xu Date: Tue, 15 May 2012 03:13:54 +0800 Subject: [PATCH] add: OrbitalControls --- src/extras/controls/OrbitalControls.js | 152 +++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/extras/controls/OrbitalControls.js diff --git a/src/extras/controls/OrbitalControls.js b/src/extras/controls/OrbitalControls.js new file mode 100644 index 0000000000..f1f4661c76 --- /dev/null +++ b/src/extras/controls/OrbitalControls.js @@ -0,0 +1,152 @@ +/** + * @author qiao / https://github.com/qiao + */ + +THREE.OrbitalControls = function( object, domElement ) { + + this.object = object; + this.domElement = ( domElement !== undefined ? domElement : document ); + + // API + + this.center = new THREE.Vector3( 0, 0, 0 ); + + this.userZoom = true; + this.userZoomSpeed = 1.0; + + this.userRotate = true; + this.userRotateSpeed = 2.0; + + this.autoRotate = false; + this.autoRotateSpeed = 3.0; // 20 seconds per round when fps is 60 + + // internals + + var EPS = 0.000001; + var PIXELS_PER_ROUND = 1800; + + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + var rotating = false; + var phiDelta = 0; + var thetaDelta = 0; + var scale = 1; + + this.update = function () { + + var position = this.object.position; + + // angle from z-axis around y-axis + var theta = Math.atan2( position.x, position.z ); + + // angle from y-axis + var phi = Math.atan2( + Math.sqrt( position.x * position.x + position.z * position.z ), + position.y + ); + + if ( this.autoRotate ) { + + theta += 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + + } + + if ( this.userRotate ) { + + theta += thetaDelta; + phi += phiDelta; + + // restrict phi to be betwee EPS and PI-EPS + phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); + + thetaDelta = 0; + phiDelta = 0; + + } + + var radius = position.clone().subSelf( this.center ).length(); + var offset = new THREE.Vector3(); + offset.x = radius * Math.sin( phi ) * Math.sin( theta ); + offset.y = radius * Math.cos( phi ); + offset.z = radius * Math.sin( phi ) * Math.cos( theta ); + + if ( this.userZoom ) { + + offset.multiplyScalar( scale ); + scale = 1; + + } + + position.copy( this.center ).addSelf( offset ); + + this.object.lookAt( this.center ); + + }; + + var self = this; + + function onMouseMove( event ) { + + if ( !rotating ) return; + + rotateEnd.set( event.clientX, event.clientY ); + rotateDelta.sub( rotateEnd, rotateStart ); + + thetaDelta = -2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * self.userRotateSpeed; + phiDelta = -2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * self.userRotateSpeed; + + rotateStart.copy( rotateEnd ); + + } + + function onMouseDown( event ) { + + if ( !self.userRotate ) return; + + rotateStart.set( event.clientX, event.clientY ); + rotating = true; + + } + + function onMouseUp( event ) { + + if ( !self.userRotate ) return; + + rotating = false; + + } + + function onMouseWheel( event ) { + + if ( !self.userZoom ) return; + + if ( event.wheelDelta > 0 ) { + + scale = Math.pow( 0.95, self.userZoomSpeed ); + + } else { + + scale = 1.0 / Math.pow( 0.95, self.userZoomSpeed ); + + } + + } + + function onKeyDown( event ) { + + } + + function onKeyUp( event ) { + + } + + this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false ); + this.domElement.addEventListener( 'mousemove', onMouseMove, false ); + this.domElement.addEventListener( 'mousedown', onMouseDown, false ); + this.domElement.addEventListener( 'mouseup', onMouseUp, false ); + this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); + this.domElement.addEventListener( 'keydown', onKeyDown, false ); + this.domElement.addEventListener( 'keyup', onKeyUp, false ); + +}; -- GitLab