Browse Source

restructured TrackballCamera, final static moving version

Eberhard Gräther 14 years ago
parent
commit
3fcc39301b
1 changed files with 164 additions and 184 deletions
  1. 164 184
      src/extras/cameras/TrackballCamera.js

+ 164 - 184
src/extras/cameras/TrackballCamera.js

@@ -9,6 +9,7 @@
  *	target: <THREE.Object3D>,
  *	target: <THREE.Object3D>,
 
 
  *	radius: <float>,
  *	radius: <float>,
+ *	screen: { width : <float>, height : <float>, offsetLeft : <float>, offsetTop : <float> },
 
 
  *	zoomSpeed: <float>,
  *	zoomSpeed: <float>,
  *	panSpeed: <float>,
  *	panSpeed: <float>,
@@ -16,307 +17,286 @@
  *	noZoom: <bool>,
  *	noZoom: <bool>,
  *	noPan: <bool>,
  *	noPan: <bool>,
 
 
- *	keys: <Array>, // [ rotateKey, zoomKey, panKey ]
+ *	keys: <Array>, // [ rotateKey, zoomKey, panKey ],
 
 
  *	domElement: <HTMLElement>,
  *	domElement: <HTMLElement>,
  * }
  * }
  */
  */
 
 
-// TODO: onWindowResize();
-
 THREE.TrackballCamera = function ( parameters ) {
 THREE.TrackballCamera = function ( parameters ) {
 
 
-	THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target );
-	
-	this.radius = ( window.innerWidth + window.innerHeight ) / 4;
-	
-	this.zoomSpeed = 1.0;
-	this.panSpeed = 1.0;
-
-	this.noZoom = false;
-	this.noPan = false;
-
-	this.keys = [ 65, 83, 68 ];
-	this.keyPressed = false;
+	// target.position is modified when panning
 
 
-	this.domElement = document;
+	parameters = parameters || {};
 
 
-	if ( parameters ) {
-
-		if ( parameters.radius !== undefined ) this.radius = parameters.radius;
+	THREE.Camera.call( this, parameters.fov, parameters.aspect, parameters.near, parameters.far, parameters.target );
 
 
-		if ( parameters.zoomSpeed !== undefined ) this.zoomSpeed = parameters.zoomSpeed;
-		if ( parameters.panSpeed !== undefined ) this.panSpeed = parameters.panSpeed;
+	this.domElement = parameters.domElement || document;
 
 
-		if ( parameters.noZoom !== undefined ) this.noZoom = parameters.noZoom;
-		if ( parameters.noPan !== undefined ) this.noPan = parameters.noPan;
+	this.screen = parameters.screen || { width : window.innerWidth, height : window.innerHeight, offsetLeft : 0, offsetTop : 0 };
+	this.radius = parameters.radius || ( this.screen.width + this.screen.height ) / 4;
 
 
-		if ( parameters.keys !== undefined ) this.keys = parameters.keys;
+	this.zoomSpeed = parameters.zoomSpeed || 1.5;
+	this.panSpeed = parameters.panSpeed || 0.3;
 
 
-		if ( parameters.domElement !== undefined ) this.domElement = parameters.domElement;
+	this.noZoom = parameters.noZoom || false;
+	this.noPan = parameters.noPan || false;
 
 
-	}
+	this.keys = parameters.keys || [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
 
 
 	this.useTarget = true;
 	this.useTarget = true;
 
 
-	this.state = this.STATE.NONE;
-	this.screen = this.getScreenDimensions();
 
 
-	this.mouse = new THREE.Vector2();
+	//internals
 
 
-	this.start = new THREE.Vector3();
-	this.end = new THREE.Vector3();
+	var _keyPressed = false,
 	
 	
-	function bind( scope, fn ) {
+	_state = this.STATE.NONE,
+	
+	_mouse = new THREE.Vector2(),
+	
+	_start = new THREE.Vector3(),
+	_end = new THREE.Vector3();
 
 
-		return function () {
 
 
-			fn.apply( scope, arguments );
+	// methods
 
 
-		};
+	this.handleEvent = function ( event ) {
 
 
-	};
-	
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
-	
-	this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
-	this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
-	this.domElement.addEventListener( 'mouseup',   bind( this, this.mouseup ), false );
+		if ( typeof this[ event.type ] == 'function' ) {
 
 
-	window.addEventListener( 'keydown', bind( this, this.keydown ), false );
-	window.addEventListener( 'keyup',   bind( this, this.keyup ), false );
-	
-};
+			this[ event.type ]( event );
 
 
-THREE.TrackballCamera.prototype = new THREE.Camera();
-THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera;
-THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype;
+		}
 
 
-THREE.TrackballCamera.prototype.STATE = {
-	NONE : -1,
-	ROTATE : 0,
-	ZOOM : 1,
-	PAN : 2
-};
+	};
 
 
-THREE.TrackballCamera.prototype.handleEvent = function ( event ) {
+	this.getMouseOnScreen = function( clientX, clientY ) {
 
 
-	if ( typeof this[ event.type ] == 'function' ) {
+		return new THREE.Vector2(
+			( clientX - this.screen.offsetLeft ) / this.radius * 0.5,
+			( clientY - this.screen.offsetTop ) / this.radius * 0.5
+		);
 
 
-		this[ event.type ]( event );
+	};
 
 
-	}
+	this.getMouseProjectionOnBall = function( clientX, clientY ) {
 
 
-};
+		var mouseOnBall = new THREE.Vector3(
+			( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius,
+			( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius,
+			0.0
+		);
 
 
-THREE.TrackballCamera.prototype.keydown = function( event ) {
-	
-	if ( this.state !== this.STATE.NONE ) {
+		var length = mouseOnBall.length();
 
 
-		return;
+		if ( length > 1.0 ) {
 
 
-	} else if ( event.keyCode === this.keys[ this.STATE.ROTATE ] ) {
+			mouseOnBall.normalize();
 
 
-		this.state = this.STATE.ROTATE;
-		this.keyPressed = true;
+		} else {
 
 
-	} else if ( event.keyCode === this.keys[ this.STATE.ZOOM ] ) {
+			mouseOnBall.z = Math.sqrt( 1.0 - length * length );
 
 
-		this.state = this.STATE.ZOOM;
-		this.keyPressed = true;
+		}
 
 
-	} else if ( event.keyCode === this.keys[ this.STATE.PAN ] ) {
+		var projection = this.up.clone().setLength( mouseOnBall.y );
+		projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouseOnBall.x ) );
+		projection.addSelf( this.position.clone().setLength( mouseOnBall.z ) );
 
 
-		this.state = this.STATE.PAN;
-		this.keyPressed = true;
+		return projection;
 
 
-	}
+	};
 
 
-};
+	this.rotateCamera = function( clientX, clientY ) {
 
 
-THREE.TrackballCamera.prototype.keyup = function( event ) {
+		_end = this.getMouseProjectionOnBall( clientX, clientY );
 
 
-	if ( this.state !== this.STATE.NONE ) {
+		var angle = Math.acos( _start.dot( _end ) / _start.length() / _end.length() );
 
 
-		this.state = this.STATE.NONE;
+		if ( angle ) {
 
 
-	}
+			var axis = (new THREE.Vector3()).cross( _end, _start ).normalize(),
+			quaternion = new THREE.Quaternion();
 
 
-};
+			quaternion.setFromAxisAngle( axis, angle );
 
 
-THREE.TrackballCamera.prototype.mousedown = function(event) {
+			quaternion.multiplyVector3( this.position );
+			quaternion.multiplyVector3( this.up );
 
 
-	event.preventDefault();
-	event.stopPropagation();
+			// quaternion.setFromAxisAngle( axis, angle * -0.1 );
+			// quaternion.multiplyVector3( _start );
 
 
-	if ( this.state === this.STATE.NONE ) {
+		}
 
 
-		this.state = event.button;
+	};
 
 
-		if ( this.state === this.STATE.ROTATE ) {
+	this.zoomCamera = function( clientX, clientY ) {
 
 
-			this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
+		var newMouse = this.getMouseOnScreen( clientX, clientY ),
+		eye = this.position.clone().subSelf( this.target.position ),
+		factor = 1.0 + ( newMouse.y - _mouse.y ) * this.zoomSpeed;
 
 
-		} else {
+		if ( factor > 0.0 ) {
 
 
-			this.mouse = this.getMouseOnScreen( event.clientX, event.clientY );
+			this.position.add( this.target.position, eye.multiplyScalar( factor ) );
+			_mouse = newMouse;
 
 
 		}
 		}
 
 
-	}
-
-};
+	};
 
 
-THREE.TrackballCamera.prototype.mousemove = function( event ) {
-	
-	if ( this.keyPressed ) {
+	this.panCamera = function( clientX, clientY ) {
 
 
-		this.start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
-		this.mouse = this.getMouseOnScreen( event.clientX, event.clientY );
+		var newMouse = this.getMouseOnScreen( clientX, clientY ),
+		mouseChange = newMouse.clone().subSelf( _mouse ),
+		factor = this.position.distanceTo( this.target.position ) * this.panSpeed;
 
 
-		this.keyPressed = false;
+		mouseChange.multiplyScalar( factor );
 
 
-	}
+		var pan = this.position.clone().crossSelf( this.up ).setLength( mouseChange.x );
+		pan.addSelf( this.up.clone().setLength( mouseChange.y ) );
 
 
-	if ( this.state === this.STATE.NONE ) {
+		this.position.addSelf( pan );
+		this.target.position.addSelf( pan );
 
 
-		return;
+		_mouse = newMouse;
 
 
-	} else if ( this.state === this.STATE.ROTATE ) {
+	};
+	
+	// this.update = function( parentMatrixWorld, forceUpdate, camera ) {
+	// 
+	// 	this.rotateCamera();
+	// 
+	// 	this.supr.update.call( this, parentMatrixWorld, forceUpdate, camera );
+	// 
+	// };
 
 
-		this.rotateCamera( event.clientX, event.clientY );
+	// listeners
 
 
-	} else if ( this.state === this.STATE.ZOOM && !this.noZoom ) {
+	function keydown( event ) {
 
 
-		this.zoomCamera( event.clientX, event.clientY );
+		if ( _state !== this.STATE.NONE ) {
 
 
-	} else if ( this.state === this.STATE.PAN && !this.noPan ) {
+			return;
 
 
-		this.panCamera( event.clientX, event.clientY );
+		} else if ( event.keyCode === this.keys[ this.STATE.ROTATE ] ) {
 
 
-	}
+			_state = this.STATE.ROTATE;
+			_keyPressed = true;
 
 
-};
+		} else if ( event.keyCode === this.keys[ this.STATE.ZOOM ] ) {
 
 
-THREE.TrackballCamera.prototype.mouseup = function( event ) {
+			_state = this.STATE.ZOOM;
+			_keyPressed = true;
 
 
-	event.preventDefault();
-	event.stopPropagation();
+		} else if ( event.keyCode === this.keys[ this.STATE.PAN ] ) {
 
 
-	this.state = this.STATE.NONE;
+			_state = this.STATE.PAN;
+			_keyPressed = true;
 
 
-};
+		}
 
 
-THREE.TrackballCamera.prototype.getScreenDimensions = function() {
+	};
 
 
-	if ( this.domElement != document ) {
+	function keyup( event ) {
 
 
-		return {
-			width : this.domElement.offsetWidth, 
-			height : this.domElement.offsetHeight,
-			offsetLeft : this.domElement.offsetLeft,
-			offsetTop : this.domElement.offsetTop
-		};
+		if ( _state !== this.STATE.NONE ) {
 
 
-	} else {
+			_state = this.STATE.NONE;
 
 
-		return {
-			width : window.innerWidth, 
-			height : window.innerHeight,
-			offsetLeft : 0,
-			offsetTop : 0
-		};
+		}
 
 
-	}
+	};
 
 
-};
+	function mousedown(event) {
 
 
-THREE.TrackballCamera.prototype.getMouseOnScreen = function( clientX, clientY ) {
+		event.preventDefault();
+		event.stopPropagation();
 
 
-	return new THREE.Vector2(
-		( clientX - this.screen.offsetLeft ) / this.radius * 0.5,
-		( clientY - this.screen.offsetTop ) / this.radius * 0.5
-	);
+		if ( _state === this.STATE.NONE ) {
 
 
-};
+			_state = event.button;
 
 
-THREE.TrackballCamera.prototype.getMouseProjectionOnBall = function( clientX, clientY ) {
+			if ( _state === this.STATE.ROTATE ) {
 
 
-	var mouseOnBall = new THREE.Vector3(
-		( clientX - this.screen.width * 0.5 - this.screen.offsetLeft ) / this.radius,
-		( this.screen.height * 0.5 + this.screen.offsetTop - clientY ) / this.radius,
-		0.0
-	);
+				_start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
 
 
-	var length = mouseOnBall.length();
+			} else {
 
 
-	if ( length > 1.0 ) {
+				_mouse = this.getMouseOnScreen( event.clientX, event.clientY );
 
 
-		mouseOnBall.normalize();
+			}
 
 
-	} else {
+		}
 
 
-		mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+	};
 
 
-	}
+	function mousemove( event ) {
 
 
-	var projection = this.up.clone().setLength( mouseOnBall.y );
-	projection.addSelf( this.up.clone().crossSelf( this.position ).setLength( mouseOnBall.x ) );
-	projection.addSelf( this.position.clone().setLength( mouseOnBall.z ) );
+		if ( _keyPressed ) {
 
 
-	return projection;
+			_start = this.getMouseProjectionOnBall( event.clientX, event.clientY );
+			_mouse = this.getMouseOnScreen( event.clientX, event.clientY );
 
 
-};
+			_keyPressed = false;
 
 
-THREE.TrackballCamera.prototype.rotateCamera = function( clientX, clientY ) {
+		}
 
 
-	this.end = this.getMouseProjectionOnBall( clientX, clientY );
+		if ( _state === this.STATE.NONE ) {
 
 
-	var angle = Math.acos( this.start.dot( this.end ) / this.start.length() / this.end.length() );
+			return;
 
 
-	if ( angle ) {
+		} else if ( _state === this.STATE.ROTATE ) {
 
 
-		var axis = (new THREE.Vector3()).cross( this.end, this.start ).normalize(),
-			quaternion = new THREE.Quaternion();
+			// _end = this.getMouseProjectionOnBall( event.clientX, event.clientY );
 
 
-		quaternion.setFromAxisAngle( axis, angle );
+			this.rotateCamera( event.clientX, event.clientY );
 
 
-		quaternion.multiplyVector3( this.position );
-		quaternion.multiplyVector3( this.up );
+		} else if ( _state === this.STATE.ZOOM && !this.noZoom ) {
 
 
-	}
+			this.zoomCamera( event.clientX, event.clientY );
 
 
-};
+		} else if ( _state === this.STATE.PAN && !this.noPan ) {
 
 
-THREE.TrackballCamera.prototype.zoomCamera = function( clientX, clientY ) {
+			this.panCamera( event.clientX, event.clientY );
 
 
-	var newMouse = this.getMouseOnScreen( clientX, clientY ),
-		eye = this.position.clone().subSelf( this.target.position ),
-		factor = 1.0 + ( newMouse.y - this.mouse.y ) * this.zoomSpeed;
+		}
 
 
-	if ( factor > 0.0 ) {
+	};
 
 
-		this.position.add( this.target.position, eye.multiplyScalar( factor ) );
-		this.mouse = newMouse;
+	function mouseup( event ) {
 
 
-	}
+		event.preventDefault();
+		event.stopPropagation();
 
 
-};
+		_state = this.STATE.NONE;
 
 
-THREE.TrackballCamera.prototype.panCamera = function( clientX, clientY ) {
+	};
 	
 	
-	var newMouse = this.getMouseOnScreen( clientX, clientY ),
-		mouseChange = newMouse.clone().subSelf(this.mouse),
-		factor = this.position.distanceTo( this.target.position ) * this.panSpeed;
+	function bind( scope, fn ) {
+
+		return function () {
+
+			fn.apply( scope, arguments );
 
 
-	mouseChange.multiplyScalar( factor );
+		};
 
 
-	var pan = this.position.clone().crossSelf( this.up ).setLength( mouseChange.x );
-	pan.addSelf( this.up.clone().setLength( mouseChange.y ) );
+	};
+
+	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
 
 
-	this.position.addSelf( pan );
-	this.target.position.addSelf( pan );
+	this.domElement.addEventListener( 'mousemove', bind( this, mousemove ), false );
+	this.domElement.addEventListener( 'mousedown', bind( this, mousedown ), false );
+	this.domElement.addEventListener( 'mouseup',   bind( this, mouseup ), false );
 
 
-	this.mouse = newMouse;
+	window.addEventListener( 'keydown', bind( this, keydown ), false );
+	window.addEventListener( 'keyup',   bind( this, keyup ), false );
 
 
 };
 };
+
+THREE.TrackballCamera.prototype = new THREE.Camera();
+THREE.TrackballCamera.prototype.constructor = THREE.TrackballCamera;
+THREE.TrackballCamera.prototype.supr = THREE.Camera.prototype;
+
+THREE.TrackballCamera.prototype.STATE = { NONE : -1, ROTATE : 0, ZOOM : 1, PAN : 2 };