Selaa lähdekoodia

TrackballControls: Implemented multi touch rotate. (#24215)

* Examples: implemented multi touch rotate for trackball controls

* Added flag to optionally enable touch rotate for `TrackballControls`

* Removed `multiTouchRotate` from constructor arguments
Nicu 2 vuotta sitten
vanhempi
commit
8d2fb0830d

+ 70 - 1
examples/jsm/controls/TrackballControls.js

@@ -19,6 +19,8 @@ class TrackballControls extends EventDispatcher {
 		const scope = this;
 		const STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
 
+		this.multiTouchRotate = false;
+
 		this.object = object;
 		this.domElement = domElement;
 		this.domElement.style.touchAction = 'none'; // disable touch scroll
@@ -33,6 +35,8 @@ class TrackballControls extends EventDispatcher {
 		this.zoomSpeed = 1.2;
 		this.panSpeed = 0.3;
 
+		this.rotateThreshold = 0.5;
+
 		this.noRotate = false;
 		this.noZoom = false;
 		this.noPan = false;
@@ -64,6 +68,11 @@ class TrackballControls extends EventDispatcher {
 
 			_lastAngle = 0;
 
+		let _touchRotationAnglePrev = 0;
+		let _touchRotationAngleNew = 0;
+		let _touchRotationAngleDelta = 0;
+		let _pointersSet = {};
+
 		const _eye = new Vector3(),
 
 			_movePrev = new Vector2(),
@@ -149,7 +158,30 @@ class TrackballControls extends EventDispatcher {
 				moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
 				let angle = moveDirection.length();
 
-				if ( angle ) {
+				if ( this.multiTouchRotate && _state === STATE.TOUCH_ZOOM_PAN ) {
+
+					_touchRotationAngleDelta = _touchRotationAngleNew - _touchRotationAnglePrev;
+					_touchRotationAnglePrev = _touchRotationAngleNew;
+					if (
+						_touchRotationAngleDelta &&
+							Math.abs( _touchRotationAngleDelta ) < this.rotateThreshold
+					) {
+
+						angle = _touchRotationAngleDelta;
+						_eye.copy( scope.object.position ).sub( scope.target );
+
+						eyeDirection.copy( _eye ).normalize();
+
+						quaternion.setFromAxisAngle( eyeDirection, angle );
+
+						scope.object.up.applyQuaternion( quaternion );
+
+						_lastAxis.copy( eyeDirection );
+						_lastAngle = angle;
+
+					}
+
+				} else if ( angle && Math.abs( angle ) < this.rotateThreshold ) {
 
 					_eye.copy( scope.object.position ).sub( scope.target );
 
@@ -629,6 +661,8 @@ class TrackballControls extends EventDispatcher {
 		function onTouchStart( event ) {
 
 			trackPointer( event );
+			_pointersSet = {};
+			gatherPointers( event );
 
 			switch ( _pointers.length ) {
 
@@ -644,6 +678,11 @@ class TrackballControls extends EventDispatcher {
 					const dy = _pointers[ 0 ].pageY - _pointers[ 1 ].pageY;
 					_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
 
+					_touchRotationAnglePrev = Math.atan2(
+						_pointers[ 0 ].pageY - _pointers[ 1 ].pageY,
+						_pointers[ 0 ].pageX - _pointers[ 1 ].pageX
+					);
+
 					const x = ( _pointers[ 0 ].pageX + _pointers[ 1 ].pageX ) / 2;
 					const y = ( _pointers[ 0 ].pageY + _pointers[ 1 ].pageY ) / 2;
 					_panStart.copy( getMouseOnScreen( x, y ) );
@@ -659,6 +698,7 @@ class TrackballControls extends EventDispatcher {
 		function onTouchMove( event ) {
 
 			trackPointer( event );
+			const points = gatherPointers( event );
 
 			switch ( _pointers.length ) {
 
@@ -675,6 +715,15 @@ class TrackballControls extends EventDispatcher {
 					const dy = event.pageY - position.y;
 					_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
 
+					if ( points ) {
+
+						_touchRotationAngleNew = Math.atan2(
+							points[ 0 ].y - points[ 1 ].y,
+							points[ 0 ].x - points[ 1 ].x
+						);
+
+					}
+
 					const x = ( event.pageX + position.x ) / 2;
 					const y = ( event.pageY + position.y ) / 2;
 					_panEnd.copy( getMouseOnScreen( x, y ) );
@@ -768,6 +817,26 @@ class TrackballControls extends EventDispatcher {
 
 		}
 
+		function gatherPointers( event ) {
+
+			_pointersSet[ event.pointerId ] = event;
+
+			if ( Object.keys( _pointersSet ).length === _pointers.length ) {
+
+				const result = _pointers.map( function ( pointer ) {
+
+					return _pointersSet[ pointer.pointerId ];
+
+				} );
+
+				return result;
+
+			}
+
+			return false;
+
+		}
+
 		function getSecondPointerPosition( event ) {
 
 			const pointer = ( event.pointerId === _pointers[ 0 ].pointerId ) ? _pointers[ 1 ] : _pointers[ 0 ];

+ 1 - 0
examples/misc_controls_trackball.html

@@ -132,6 +132,7 @@
 
 				controls = new TrackballControls( camera, renderer.domElement );
 
+				controls.multiTouchRotate = true;
 				controls.rotateSpeed = 1.0;
 				controls.zoomSpeed = 1.2;
 				controls.panSpeed = 0.8;