Browse Source

Dolly translates camera rather than scales its distance

At least on Macs, trackpad swipes already trigger a sequence of
mousewheel events with smoothly damped deltas, continuing after the
fingers have been lifted from the pad. Unfortunately, the intuitive,
smoothly damped dollying motion that this would cause is canceled by the
exponential zooming behavior (multiplying or dividing the current
distance by a fixed value).

It feels much better to dolly in and out in a linear manner, as this
patch does. The change is especially noticable if
(maxDistance-minDistance) is finite.

Note that different browsers produce mousewheel deltas with different
scales. This patch copies some code from TrackballControls to normalize
to a common scale.
Leo Singer 11 years ago
parent
commit
75e2e813db
1 changed files with 20 additions and 28 deletions
  1. 20 28
      examples/js/controls/OrbitControls.js

+ 20 - 28
examples/js/controls/OrbitControls.js

@@ -103,7 +103,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 	var phiDelta = 0;
 	var thetaDelta = 0;
-	var scale = 1;
+	var radius = object.position.length();
 	var pan = new THREE.Vector3();
 
 	var lastPosition = new THREE.Vector3();
@@ -213,27 +213,15 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 	};
 
-	this.dollyIn = function ( dollyScale ) {
+	this.dollyIn = function ( dolly ) {
 
-		if ( dollyScale === undefined ) {
-
-			dollyScale = getZoomScale();
-
-		}
-
-		scale /= dollyScale;
+		radius -= getZoomSpeed() * dolly;
 
 	};
 
-	this.dollyOut = function ( dollyScale ) {
-
-		if ( dollyScale === undefined ) {
+	this.dollyOut = function ( dolly ) {
 
-			dollyScale = getZoomScale();
-
-		}
-
-		scale *= dollyScale;
+		radius += getZoomSpeed() * dolly;
 
 	};
 
@@ -279,8 +267,6 @@ THREE.OrbitControls = function ( object, domElement ) {
 		// 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( this.minDistance, Math.min( this.maxDistance, radius ) );
 		
@@ -298,7 +284,6 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		this.object.lookAt( this.target );
 
-		scale = 1;
 		pan.set( 0, 0, 0 );
 
 		if ( lastPosition.distanceToSquared( this.object.position ) > EPS ) {
@@ -329,9 +314,14 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 	}
 
-	function getZoomScale() {
+	function getZoomSpeed() {
 
-		return Math.pow( 0.95, scope.zoomSpeed );
+		var distanceRange = this.maxDistance - this.minDistance;
+
+		if ( distanceRange < Infinity )
+			return distanceRange * scope.zoomSpeed;
+		else
+			return scope.zoomSpeed;
 
 	}
 
@@ -401,11 +391,11 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 			if ( dollyDelta.y > 0 ) {
 
-				scope.dollyIn();
+				scope.dollyIn( dollyDelta.y );
 
 			} else {
 
-				scope.dollyOut();
+				scope.dollyOut( -dollyDelta.y );
 
 			}
 
@@ -432,6 +422,8 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		if ( scope.enabled === false ) return;
 
+		_state = STATE.NONE;
+
 		scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
 		scope.domElement.removeEventListener( 'mouseup', onMouseUp, false );
 		scope.dispatchEvent( endEvent );
@@ -450,21 +442,21 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9
 
-			delta = event.wheelDelta;
+			delta = event.wheelDelta / 40;
 
 		} else if ( event.detail !== undefined ) { // Firefox
 
-			delta = - event.detail;
+			delta = - event.detail / 3;
 
 		}
 
 		if ( delta > 0 ) {
 
-			scope.dollyOut();
+			scope.dollyOut( delta );
 
 		} else {
 
-			scope.dollyIn();
+			scope.dollyIn( -delta );
 
 		}