Jelajahi Sumber

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 tahun lalu
induk
melakukan
75e2e813db
1 mengubah file dengan 20 tambahan dan 28 penghapusan
  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 );
 
 		}